aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2021-09-28 15:26:46 +0100
committerJonathan Wakely <jwakely@redhat.com>2021-09-28 20:22:50 +0100
commit82626be2d633a9802a8b08727ef51c627e37fee5 (patch)
tree42611665bfec6c2fee6ef6035b7ac92038171fd4
parentb12d6e79899fd27833c53ffc3c973538244f62e1 (diff)
downloadgcc-82626be2d633a9802a8b08727ef51c627e37fee5.zip
gcc-82626be2d633a9802a8b08727ef51c627e37fee5.tar.gz
gcc-82626be2d633a9802a8b08727ef51c627e37fee5.tar.bz2
libstdc++: Specialize std::pointer_traits<__normal_iterator<I,C>>
This allows std::__to_address to be used with __normal_iterator in C++11/14/17 modes. Without the partial specialization the deduced pointer_traits::element_type is incorrect, and so the return type of __to_address is wrong. A similar partial specialization is probably needed for __gnu_debug::_Safe_iterator. Signed-off-by: Jonathan Wakely <jwakely@redhat.com> libstdc++-v3/ChangeLog: * include/bits/stl_iterator.h (pointer_traits): Define partial specialization for __normal_iterator. * testsuite/24_iterators/normal_iterator/to_address.cc: New test.
-rw-r--r--libstdc++-v3/include/bits/stl_iterator.h28
-rw-r--r--libstdc++-v3/testsuite/24_iterators/normal_iterator/to_address.cc6
2 files changed, 34 insertions, 0 deletions
diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h
index c5b0240..004d767 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -1285,6 +1285,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __it.base(); }
#if __cplusplus >= 201103L
+
+ // Need to specialize pointer_traits because the primary template will
+ // deduce element_type of __normal_iterator<T*, C> as T* rather than T.
+ template<typename _Iterator, typename _Container>
+ struct pointer_traits<__gnu_cxx::__normal_iterator<_Iterator, _Container>>
+ {
+ private:
+ using _Base = pointer_traits<_Iterator>;
+
+ public:
+ using element_type = typename _Base::element_type;
+ using pointer = __gnu_cxx::__normal_iterator<_Iterator, _Container>;
+ using difference_type = typename _Base::difference_type;
+
+ template<typename _Tp>
+ using rebind = __gnu_cxx::__normal_iterator<_Tp, _Container>;
+
+ static pointer
+ pointer_to(element_type& __e) noexcept
+ { return pointer(_Base::pointer_to(__e)); }
+
+#if __cplusplus >= 202002L
+ static element_type*
+ to_address(pointer __p) noexcept
+ { return __p.base(); }
+#endif
+ };
+
/**
* @addtogroup iterators
* @{
diff --git a/libstdc++-v3/testsuite/24_iterators/normal_iterator/to_address.cc b/libstdc++-v3/testsuite/24_iterators/normal_iterator/to_address.cc
new file mode 100644
index 0000000..510d627
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/normal_iterator/to_address.cc
@@ -0,0 +1,6 @@
+// { dg-do compile { target { c++11 } } }
+#include <string>
+#include <memory>
+
+char* p = std::__to_address(std::string("1").begin());
+const char* q = std::__to_address(std::string("2").cbegin());