diff --git a/libcxx/include/__iterator/iterator_traits.h b/libcxx/include/__iterator/iterator_traits.h index ebffc974f0e1a4..307ee143c1d2ff 100644 --- a/libcxx/include/__iterator/iterator_traits.h +++ b/libcxx/include/__iterator/iterator_traits.h @@ -428,7 +428,7 @@ struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*> template >::value> struct __has_iterator_category_convertible_to - : _BoolConstant::iterator_category, _Up>::value> + : is_convertible::iterator_category, _Up> {}; template @@ -436,7 +436,7 @@ struct __has_iterator_category_convertible_to<_Tp, _Up, false> : false_type {}; template ::value> struct __has_iterator_concept_convertible_to - : _BoolConstant::value> + : is_convertible {}; template @@ -454,10 +454,12 @@ struct __is_cpp17_bidirectional_iterator : public __has_iterator_category_conver template struct __is_cpp17_random_access_iterator : public __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag> {}; -// __is_cpp17_contiguous_iterator determines if an iterator is contiguous, -// either because it advertises itself as such (in C++20) or because it -// is a pointer type or a known trivial wrapper around a pointer type, -// such as __wrap_iter. +// __is_cpp17_contiguous_iterator determines if an iterator is known by +// libc++ to be contiguous, either because it advertises itself as such +// (in C++20) or because it is a pointer type or a known trivial wrapper +// around a (possibly fancy) pointer type, such as __wrap_iter. +// Such iterators receive special "contiguous" optimizations in +// std::copy and std::sort. // #if _LIBCPP_STD_VER > 17 template diff --git a/libcxx/include/iterator b/libcxx/include/iterator index 6bc98ecb6774fe..e3d1360971e7dd 100644 --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -1294,8 +1294,7 @@ public: typedef typename iterator_traits::reference reference; typedef typename iterator_traits::iterator_category iterator_category; #if _LIBCPP_STD_VER > 17 - typedef _If<__is_cpp17_contiguous_iterator<_Iter>::value, - contiguous_iterator_tag, iterator_category> iterator_concept; + typedef contiguous_iterator_tag iterator_concept; #endif private: @@ -1473,12 +1472,12 @@ private: #if _LIBCPP_STD_VER <= 17 template -struct __is_cpp17_contiguous_iterator<__wrap_iter<_It> > : __is_cpp17_contiguous_iterator<_It> {}; +struct __is_cpp17_contiguous_iterator<__wrap_iter<_It> > : true_type {}; #endif template _LIBCPP_CONSTEXPR -_EnableIf<__is_cpp17_contiguous_iterator<_Iter>::value, decltype(_VSTD::__to_address(declval<_Iter>()))> +decltype(_VSTD::__to_address(declval<_Iter>())) __to_address(__wrap_iter<_Iter> __w) _NOEXCEPT { return _VSTD::__to_address(__w.base()); } diff --git a/libcxx/test/libcxx/iterators/contiguous_iterators.pass.cpp b/libcxx/test/libcxx/iterators/contiguous_iterators.pass.cpp index 06d8c38eb2243d..8899ffcd356248 100644 --- a/libcxx/test/libcxx/iterators/contiguous_iterators.pass.cpp +++ b/libcxx/test/libcxx/iterators/contiguous_iterators.pass.cpp @@ -138,6 +138,21 @@ class my_contiguous_iterator }; #endif +struct fake_deque_iterator : std::deque::iterator { + using element_type = int; +}; +static_assert(std::__is_cpp17_random_access_iterator::value, ""); +static_assert(!std::__is_cpp17_contiguous_iterator::value, ""); + +#if TEST_STD_VER >= 20 +struct fake2_deque_iterator : std::deque::iterator { + using iterator_concept = std::contiguous_iterator_tag; + using element_type = int; +}; +static_assert(std::__is_cpp17_random_access_iterator::value, ""); +static_assert(std::__is_cpp17_contiguous_iterator::value, ""); +#endif + int main(int, char**) { // basic tests @@ -178,21 +193,19 @@ int main(int, char**) static_assert(( std::__is_cpp17_contiguous_iterator >::value), ""); static_assert(( std::__is_cpp17_contiguous_iterator > >::value), ""); - static_assert((!std::__is_cpp17_contiguous_iterator > >::value), ""); - static_assert((!std::__is_cpp17_contiguous_iterator >::value), ""); - static_assert((!std::__is_cpp17_contiguous_iterator > >::value), ""); - static_assert((!std::__is_cpp17_contiguous_iterator > >::value), ""); + // Here my_random_access_iterator is standing in for some user's fancy pointer type, written pre-C++20. + static_assert(( std::__is_cpp17_contiguous_iterator >::value), ""); + static_assert(( std::__is_cpp17_contiguous_iterator > >::value), ""); #if TEST_STD_VER >= 20 static_assert(( std::__is_cpp17_contiguous_iterator >::value), ""); static_assert(( std::__is_cpp17_contiguous_iterator > >::value), ""); - static_assert((!std::__is_cpp17_contiguous_iterator > >::value), ""); #endif // iterators in the libc++ test suite static_assert((!std::__is_cpp17_contiguous_iterator >::value), ""); - static_assert((!std::__is_cpp17_contiguous_iterator >::value), ""); + static_assert((!std::__is_cpp17_contiguous_iterator >::value), ""); static_assert((!std::__is_cpp17_contiguous_iterator >::value), ""); static_assert((!std::__is_cpp17_contiguous_iterator >::value), ""); static_assert((!std::__is_cpp17_contiguous_iterator >::value), ""); @@ -228,14 +241,12 @@ int main(int, char**) static_assert((!std::__is_cpp17_contiguous_iterator::const_iterator> ::value), ""); static_assert((!std::__is_cpp17_contiguous_iterator::reverse_iterator> ::value), ""); static_assert((!std::__is_cpp17_contiguous_iterator::const_reverse_iterator> ::value), ""); - static_assert((!std::__is_cpp17_contiguous_iterator::iterator> >::value), ""); // vector is random-access but not contiguous static_assert((!std::__is_cpp17_contiguous_iterator::iterator> ::value), ""); static_assert((!std::__is_cpp17_contiguous_iterator::const_iterator> ::value), ""); static_assert((!std::__is_cpp17_contiguous_iterator::reverse_iterator> ::value), ""); static_assert((!std::__is_cpp17_contiguous_iterator::const_reverse_iterator> ::value), ""); - static_assert((!std::__is_cpp17_contiguous_iterator::iterator> >::value), ""); #if TEST_STD_VER >= 11 static_assert(( std::__is_cpp17_contiguous_iterator::iterator> ::value), "");