[libc++] Move _ITER_TRAITS and _ITER_CONCEPT into <__iterator/concepts.h> (#140528)
`_ITER_TRAITS` and `_ITER_CONCEPT` are really implenentation details of `<__iterator/concetps.h>`, so it makes more sense to put them there than into `<__iterator/iterator_traits.h>`.
This commit is contained in:
@@ -29,16 +29,19 @@
|
||||
#include <__iterator/incrementable_traits.h>
|
||||
#include <__iterator/iter_move.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__iterator/readable_traits.h>
|
||||
#include <__memory/pointer_traits.h>
|
||||
#include <__type_traits/add_pointer.h>
|
||||
#include <__type_traits/common_reference.h>
|
||||
#include <__type_traits/conditional.h>
|
||||
#include <__type_traits/disjunction.h>
|
||||
#include <__type_traits/enable_if.h>
|
||||
#include <__type_traits/integral_constant.h>
|
||||
#include <__type_traits/invoke.h>
|
||||
#include <__type_traits/is_pointer.h>
|
||||
#include <__type_traits/is_primary_template.h>
|
||||
#include <__type_traits/is_reference.h>
|
||||
#include <__type_traits/is_referenceable.h>
|
||||
#include <__type_traits/is_valid_expansion.h>
|
||||
#include <__type_traits/remove_cv.h>
|
||||
#include <__type_traits/remove_cvref.h>
|
||||
#include <__utility/forward.h>
|
||||
@@ -151,6 +154,42 @@ concept sized_sentinel_for =
|
||||
{ __i - __s } -> same_as<iter_difference_t<_Ip>>;
|
||||
};
|
||||
|
||||
template <class _Iter>
|
||||
struct __iter_traits_cache {
|
||||
using type _LIBCPP_NODEBUG =
|
||||
_If<__is_primary_template<iterator_traits<_Iter> >::value, _Iter, iterator_traits<_Iter> >;
|
||||
};
|
||||
template <class _Iter>
|
||||
using _ITER_TRAITS _LIBCPP_NODEBUG = typename __iter_traits_cache<_Iter>::type;
|
||||
|
||||
struct __iter_concept_concept_test {
|
||||
template <class _Iter>
|
||||
using _Apply _LIBCPP_NODEBUG = typename _ITER_TRAITS<_Iter>::iterator_concept;
|
||||
};
|
||||
struct __iter_concept_category_test {
|
||||
template <class _Iter>
|
||||
using _Apply _LIBCPP_NODEBUG = typename _ITER_TRAITS<_Iter>::iterator_category;
|
||||
};
|
||||
struct __iter_concept_random_fallback {
|
||||
template <class _Iter>
|
||||
using _Apply _LIBCPP_NODEBUG =
|
||||
__enable_if_t<__is_primary_template<iterator_traits<_Iter> >::value, random_access_iterator_tag>;
|
||||
};
|
||||
|
||||
template <class _Iter, class _Tester>
|
||||
struct __test_iter_concept : _IsValidExpansion<_Tester::template _Apply, _Iter>, _Tester {};
|
||||
|
||||
template <class _Iter>
|
||||
struct __iter_concept_cache {
|
||||
using type _LIBCPP_NODEBUG =
|
||||
_Or<__test_iter_concept<_Iter, __iter_concept_concept_test>,
|
||||
__test_iter_concept<_Iter, __iter_concept_category_test>,
|
||||
__test_iter_concept<_Iter, __iter_concept_random_fallback> >;
|
||||
};
|
||||
|
||||
template <class _Iter>
|
||||
using _ITER_CONCEPT _LIBCPP_NODEBUG = typename __iter_concept_cache<_Iter>::type::template _Apply<_Iter>;
|
||||
|
||||
// [iterator.concept.input]
|
||||
template <class _Ip>
|
||||
concept input_iterator = input_or_output_iterator<_Ip> && indirectly_readable<_Ip> && requires {
|
||||
|
||||
@@ -27,14 +27,12 @@
|
||||
#include <__type_traits/conditional.h>
|
||||
#include <__type_traits/detected_or.h>
|
||||
#include <__type_traits/disjunction.h>
|
||||
#include <__type_traits/enable_if.h>
|
||||
#include <__type_traits/integral_constant.h>
|
||||
#include <__type_traits/is_convertible.h>
|
||||
#include <__type_traits/is_object.h>
|
||||
#include <__type_traits/is_primary_template.h>
|
||||
#include <__type_traits/is_reference.h>
|
||||
#include <__type_traits/is_referenceable.h>
|
||||
#include <__type_traits/is_valid_expansion.h>
|
||||
#include <__type_traits/nat.h>
|
||||
#include <__type_traits/remove_const.h>
|
||||
#include <__type_traits/remove_cv.h>
|
||||
@@ -73,42 +71,6 @@ struct random_access_iterator_tag : public bidirectional_iterator_tag {};
|
||||
struct contiguous_iterator_tag : public random_access_iterator_tag {};
|
||||
#endif
|
||||
|
||||
template <class _Iter>
|
||||
struct __iter_traits_cache {
|
||||
using type _LIBCPP_NODEBUG =
|
||||
_If<__is_primary_template<iterator_traits<_Iter> >::value, _Iter, iterator_traits<_Iter> >;
|
||||
};
|
||||
template <class _Iter>
|
||||
using _ITER_TRAITS _LIBCPP_NODEBUG = typename __iter_traits_cache<_Iter>::type;
|
||||
|
||||
struct __iter_concept_concept_test {
|
||||
template <class _Iter>
|
||||
using _Apply _LIBCPP_NODEBUG = typename _ITER_TRAITS<_Iter>::iterator_concept;
|
||||
};
|
||||
struct __iter_concept_category_test {
|
||||
template <class _Iter>
|
||||
using _Apply _LIBCPP_NODEBUG = typename _ITER_TRAITS<_Iter>::iterator_category;
|
||||
};
|
||||
struct __iter_concept_random_fallback {
|
||||
template <class _Iter>
|
||||
using _Apply _LIBCPP_NODEBUG =
|
||||
__enable_if_t<__is_primary_template<iterator_traits<_Iter> >::value, random_access_iterator_tag>;
|
||||
};
|
||||
|
||||
template <class _Iter, class _Tester>
|
||||
struct __test_iter_concept : _IsValidExpansion<_Tester::template _Apply, _Iter>, _Tester {};
|
||||
|
||||
template <class _Iter>
|
||||
struct __iter_concept_cache {
|
||||
using type _LIBCPP_NODEBUG =
|
||||
_Or<__test_iter_concept<_Iter, __iter_concept_concept_test>,
|
||||
__test_iter_concept<_Iter, __iter_concept_category_test>,
|
||||
__test_iter_concept<_Iter, __iter_concept_random_fallback> >;
|
||||
};
|
||||
|
||||
template <class _Iter>
|
||||
using _ITER_CONCEPT _LIBCPP_NODEBUG = typename __iter_concept_cache<_Iter>::type::template _Apply<_Iter>;
|
||||
|
||||
template <class _Tp>
|
||||
struct __has_iterator_typedefs {
|
||||
private:
|
||||
@@ -195,16 +157,6 @@ concept __specifies_members = requires {
|
||||
requires __has_member_iterator_category<_Ip>;
|
||||
};
|
||||
|
||||
template <class>
|
||||
struct __iterator_traits_member_pointer_or_void {
|
||||
using type _LIBCPP_NODEBUG = void;
|
||||
};
|
||||
|
||||
template <__has_member_pointer _Tp>
|
||||
struct __iterator_traits_member_pointer_or_void<_Tp> {
|
||||
using type _LIBCPP_NODEBUG = typename _Tp::pointer;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
concept __cpp17_iterator_missing_members = !__specifies_members<_Tp> && __iterator_traits_detail::__cpp17_iterator<_Tp>;
|
||||
|
||||
@@ -304,6 +256,9 @@ struct __iterator_traits_difference_type<_Ip> {
|
||||
template <class>
|
||||
struct __iterator_traits {};
|
||||
|
||||
template <class _Tp>
|
||||
using __pointer_member _LIBCPP_NODEBUG = typename _Tp::pointer;
|
||||
|
||||
// [iterator.traits]/3.1
|
||||
// If `I` has valid ([temp.deduct]) member types `difference-type`, `value-type`, `reference`, and
|
||||
// `iterator-category`, then `iterator-traits<I>` has the following publicly accessible members:
|
||||
@@ -312,7 +267,7 @@ struct __iterator_traits<_Ip> {
|
||||
using iterator_category = typename _Ip::iterator_category;
|
||||
using value_type = typename _Ip::value_type;
|
||||
using difference_type = typename _Ip::difference_type;
|
||||
using pointer = typename __iterator_traits_member_pointer_or_void<_Ip>::type;
|
||||
using pointer = __detected_or_t<void, __pointer_member, _Ip>;
|
||||
using reference = typename _Ip::reference;
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03
|
||||
// REQUIRES: std-at-least-c++20
|
||||
|
||||
// ITER_TRAITS(I)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
// random_access_iterator_tag.
|
||||
// (1.4) -- Otherwise, ITER_CONCEPT(I) does not denote a type.
|
||||
|
||||
#include <__iterator/concepts.h>
|
||||
#include <__type_traits/is_valid_expansion.h>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
@@ -30,19 +31,19 @@ struct OtherTagTwo : std::output_iterator_tag {};
|
||||
|
||||
struct MyIter {
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
using iterator_concept = int;
|
||||
using value_type = char;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = char*;
|
||||
using reference = char&;
|
||||
using iterator_concept = int;
|
||||
using value_type = char;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = char*;
|
||||
using reference = char&;
|
||||
};
|
||||
|
||||
struct MyIter2 {
|
||||
using iterator_category = OtherTag;
|
||||
using value_type = char;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = char*;
|
||||
using reference = char&;
|
||||
using value_type = char;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = char*;
|
||||
using reference = char&;
|
||||
};
|
||||
|
||||
struct MyIter3 {};
|
||||
@@ -52,10 +53,10 @@ struct EmptyWithSpecial {};
|
||||
template <>
|
||||
struct std::iterator_traits<MyIter3> {
|
||||
using iterator_category = OtherTagTwo;
|
||||
using value_type = char;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = char*;
|
||||
using reference = char&;
|
||||
using value_type = char;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = char*;
|
||||
using reference = char&;
|
||||
};
|
||||
|
||||
template <>
|
||||
@@ -63,29 +64,18 @@ struct std::iterator_traits<EmptyWithSpecial> {
|
||||
// empty non-default.
|
||||
};
|
||||
|
||||
int main(int, char**) {
|
||||
// If the qualified-id ITER_TRAITS(I)::iterator_concept is valid and names a type,
|
||||
// then ITER_CONCEPT(I) denotes that type.
|
||||
{
|
||||
#if TEST_STD_VER > 17
|
||||
ASSERT_SAME_TYPE(std::_ITER_CONCEPT<char*>, std::contiguous_iterator_tag);
|
||||
#endif
|
||||
ASSERT_SAME_TYPE(std::_ITER_CONCEPT<MyIter>, int);
|
||||
}
|
||||
// Otherwise, if the qualified-id ITER_TRAITS(I)::iterator_category is valid
|
||||
// and names a type, then ITER_CONCEPT(I) denotes that type.
|
||||
{
|
||||
ASSERT_SAME_TYPE(std::_ITER_CONCEPT<MyIter2>, OtherTag);
|
||||
ASSERT_SAME_TYPE(std::_ITER_CONCEPT<MyIter3>, OtherTagTwo);
|
||||
}
|
||||
// FIXME - This requirement makes no sense to me. Why does an empty type with
|
||||
// an empty default iterator_traits get a category of random?
|
||||
{
|
||||
ASSERT_SAME_TYPE(std::_ITER_CONCEPT<Empty>, std::random_access_iterator_tag);
|
||||
}
|
||||
{
|
||||
static_assert(!std::_IsValidExpansion<std::_ITER_CONCEPT, EmptyWithSpecial>::value, "");
|
||||
}
|
||||
// If the qualified-id ITER_TRAITS(I)::iterator_concept is valid and names a type,
|
||||
// then ITER_CONCEPT(I) denotes that type.
|
||||
ASSERT_SAME_TYPE(std::_ITER_CONCEPT<char*>, std::contiguous_iterator_tag);
|
||||
ASSERT_SAME_TYPE(std::_ITER_CONCEPT<MyIter>, int);
|
||||
|
||||
return 0;
|
||||
}
|
||||
// Otherwise, if the qualified-id ITER_TRAITS(I)::iterator_category is valid
|
||||
// and names a type, then ITER_CONCEPT(I) denotes that type.
|
||||
ASSERT_SAME_TYPE(std::_ITER_CONCEPT<MyIter2>, OtherTag);
|
||||
ASSERT_SAME_TYPE(std::_ITER_CONCEPT<MyIter3>, OtherTagTwo);
|
||||
|
||||
// FIXME - This requirement makes no sense to me. Why does an empty type with
|
||||
// an empty default iterator_traits get a category of random?
|
||||
ASSERT_SAME_TYPE(std::_ITER_CONCEPT<Empty>, std::random_access_iterator_tag);
|
||||
|
||||
static_assert(!std::_IsValidExpansion<std::_ITER_CONCEPT, EmptyWithSpecial>::value);
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03
|
||||
// REQUIRES: std-at-least-c++20
|
||||
|
||||
// ITER_TRAITS(I)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// a specialization generated from the primary template. Otherwise,
|
||||
// ITER_TRAITS(I) denotes iterator_traits<I>.
|
||||
|
||||
#include <iterator>
|
||||
#include <__iterator/concepts.h>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_iterators.h"
|
||||
@@ -27,8 +27,8 @@ template<> struct std::iterator_traits<B> {};
|
||||
template<> struct std::iterator_traits<C> : std::iterator_traits<A> {};
|
||||
template<> struct std::iterator_traits<D> : std::iterator_traits<int*> {};
|
||||
|
||||
static_assert(std::is_same<std::_ITER_TRAITS<int*>, std::iterator_traits<int*>>::value, "");
|
||||
static_assert(std::is_same<std::_ITER_TRAITS<A>, A>::value, "");
|
||||
static_assert(std::is_same<std::_ITER_TRAITS<B>, std::iterator_traits<B>>::value, "");
|
||||
static_assert(std::is_same<std::_ITER_TRAITS<C>, std::iterator_traits<C>>::value, "");
|
||||
static_assert(std::is_same<std::_ITER_TRAITS<D>, std::iterator_traits<D>>::value, "");
|
||||
static_assert(std::is_same<std::_ITER_TRAITS<int*>, std::iterator_traits<int*>>::value);
|
||||
static_assert(std::is_same<std::_ITER_TRAITS<A>, A>::value);
|
||||
static_assert(std::is_same<std::_ITER_TRAITS<B>, std::iterator_traits<B>>::value);
|
||||
static_assert(std::is_same<std::_ITER_TRAITS<C>, std::iterator_traits<C>>::value);
|
||||
static_assert(std::is_same<std::_ITER_TRAITS<D>, std::iterator_traits<D>>::value);
|
||||
|
||||
Reference in New Issue
Block a user