diff --git a/libcxx/include/__iterator/iterator_traits.h b/libcxx/include/__iterator/iterator_traits.h --- a/libcxx/include/__iterator/iterator_traits.h +++ b/libcxx/include/__iterator/iterator_traits.h @@ -11,9 +11,9 @@ #define _LIBCPP___ITERATOR_ITERATOR_TRAITS_H #include <__config> -#include #include <__iterator/incrementable_traits.h> #include <__iterator/readable_traits.h> +#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -428,7 +428,7 @@ template >::value> struct __has_iterator_category_convertible_to - : _BoolConstant::iterator_category, _Up>::value> + : is_convertible::iterator_category, _Up> {}; template @@ -436,7 +436,7 @@ template ::value> struct __has_iterator_concept_convertible_to - : _BoolConstant::value> + : is_convertible {}; template @@ -454,10 +454,11 @@ 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 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 --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -1294,8 +1294,7 @@ 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 @@ #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 --- a/libcxx/test/libcxx/iterators/contiguous_iterators.pass.cpp +++ b/libcxx/test/libcxx/iterators/contiguous_iterators.pass.cpp @@ -138,6 +138,21 @@ }; #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 @@ 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 @@ 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), "");