template <class _Tp, class _Up, bool = __has_iterator_category<iterator_traits<_Tp> >::value>
struct __has_iterator_category_convertible_to
- : _BoolConstant<is_convertible<typename iterator_traits<_Tp>::iterator_category, _Up>::value>
+ : is_convertible<typename iterator_traits<_Tp>::iterator_category, _Up>
{};
template <class _Tp, class _Up>
template <class _Tp, class _Up, bool = __has_iterator_concept<_Tp>::value>
struct __has_iterator_concept_convertible_to
- : _BoolConstant<is_convertible<typename _Tp::iterator_concept, _Up>::value>
+ : is_convertible<typename _Tp::iterator_concept, _Up>
{};
template <class _Tp, class _Up>
template <class _Tp>
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<T*>.
+// __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<T*>.
+// Such iterators receive special "contiguous" optimizations in
+// std::copy and std::sort.
//
#if _LIBCPP_STD_VER > 17
template <class _Tp>
typedef typename iterator_traits<iterator_type>::reference reference;
typedef typename iterator_traits<iterator_type>::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:
#if _LIBCPP_STD_VER <= 17
template <class _It>
-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 <class _Iter>
_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());
}
};
#endif
+struct fake_deque_iterator : std::deque<int>::iterator {
+ using element_type = int;
+};
+static_assert(std::__is_cpp17_random_access_iterator<fake_deque_iterator>::value, "");
+static_assert(!std::__is_cpp17_contiguous_iterator<fake_deque_iterator>::value, "");
+
+#if TEST_STD_VER >= 20
+struct fake2_deque_iterator : std::deque<int>::iterator {
+ using iterator_concept = std::contiguous_iterator_tag;
+ using element_type = int;
+};
+static_assert(std::__is_cpp17_random_access_iterator<fake2_deque_iterator>::value, "");
+static_assert(std::__is_cpp17_contiguous_iterator<fake2_deque_iterator>::value, "");
+#endif
+
int main(int, char**)
{
// basic tests
static_assert(( std::__is_cpp17_contiguous_iterator<std::__wrap_iter<T *> >::value), "");
static_assert(( std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::__wrap_iter<T *> > >::value), "");
- static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::reverse_iterator<T *> > >::value), "");
- static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<my_random_access_iterator> >::value), "");
- static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::__wrap_iter<my_random_access_iterator> > >::value), "");
- static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::reverse_iterator<my_random_access_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<std::__wrap_iter<my_random_access_iterator> >::value), "");
+ static_assert(( std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::__wrap_iter<my_random_access_iterator> > >::value), "");
#if TEST_STD_VER >= 20
static_assert(( std::__is_cpp17_contiguous_iterator<std::__wrap_iter<my_contiguous_iterator> >::value), "");
static_assert(( std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::__wrap_iter<my_contiguous_iterator> > >::value), "");
- static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::reverse_iterator<my_contiguous_iterator> > >::value), "");
#endif
// iterators in the libc++ test suite
static_assert((!std::__is_cpp17_contiguous_iterator<output_iterator <char *> >::value), "");
- static_assert((!std::__is_cpp17_contiguous_iterator<cpp17_input_iterator <char *> >::value), "");
+ static_assert((!std::__is_cpp17_contiguous_iterator<cpp17_input_iterator <char *> >::value), "");
static_assert((!std::__is_cpp17_contiguous_iterator<forward_iterator <char *> >::value), "");
static_assert((!std::__is_cpp17_contiguous_iterator<bidirectional_iterator<char *> >::value), "");
static_assert((!std::__is_cpp17_contiguous_iterator<random_access_iterator<char *> >::value), "");
static_assert((!std::__is_cpp17_contiguous_iterator<std::deque<int>::const_iterator> ::value), "");
static_assert((!std::__is_cpp17_contiguous_iterator<std::deque<int>::reverse_iterator> ::value), "");
static_assert((!std::__is_cpp17_contiguous_iterator<std::deque<int>::const_reverse_iterator> ::value), "");
- static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::deque<int>::iterator> >::value), "");
// vector<bool> is random-access but not contiguous
static_assert((!std::__is_cpp17_contiguous_iterator<std::vector<bool>::iterator> ::value), "");
static_assert((!std::__is_cpp17_contiguous_iterator<std::vector<bool>::const_iterator> ::value), "");
static_assert((!std::__is_cpp17_contiguous_iterator<std::vector<bool>::reverse_iterator> ::value), "");
static_assert((!std::__is_cpp17_contiguous_iterator<std::vector<bool>::const_reverse_iterator> ::value), "");
- static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::vector<bool>::iterator> >::value), "");
#if TEST_STD_VER >= 11
static_assert(( std::__is_cpp17_contiguous_iterator<std::initializer_list<int>::iterator> ::value), "");