|
- // Range v3 library
- //
- // Copyright Eric Niebler 2018-present
- //
- // Use, modification and distribution is subject to the
- // Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- //
- // Project home: https://github.com/ericniebler/range-v3
- //
-
- #ifndef RANGES_V3_STD_ITERATOR
- #define RANGES_V3_STD_ITERATOR
-
- #if defined(__GNUC__)
- #include_next <iterator>
- #elif defined(_MSC_VER)
- #include <../include/iterator> // HACKHACK
- #else
- #error "Cannot use range-v3 STL deep integration on this platform."
- #endif
-
- #if RANGES_DEEP_STL_INTEGRATION
-
- #include <range/v3/detail/config.hpp>
- #include <std/detail/associated_types.hpp>
-
- namespace ranges
- {
- template<typename I>
- struct incrementable_traits;
-
- template<typename I>
- struct readable_traits;
-
- /// \cond
- namespace detail
- {
- template<typename I>
- typename incrementable_traits<I>::difference_type cpp17_difference_type_(int);
- template<typename I>
- void cpp17_difference_type_(long);
-
- template<typename I>
- typename I::pointer cpp17_pointer_type_(int);
- template<typename I>
- auto cpp17_pointer_type_(long, I *pi = nullptr) -> decltype(pi->operator->());
- template<typename I>
- void cpp17_pointer_type_(...);
-
- template<typename I>
- typename I::reference cpp17_reference_type_(int);
- template<typename I>
- auto cpp17_reference_type_(long, I *pi = nullptr) -> decltype(**pi);
-
- template<typename I>
- auto cpp17_iterator_category_4_(long)
- {
- return std::bidirectional_iterator_tag{};
- }
- // Satisfies Cpp17RandomAccessIterator?
- template<typename I>
- auto cpp17_iterator_category_4_(
- int,
- I *pi = nullptr,
- typename incrementable_traits<I>::difference_type d = 0,
- always_<
- void,
- int[RANGES_IS_SAME(decltype(*pi += d), I &)],
- int[RANGES_IS_SAME(decltype(*pi -= d), I &)],
- int[RANGES_IS_SAME(decltype(*pi + d), I)],
- int[RANGES_IS_SAME(decltype(*pi - d), I)],
- int[RANGES_IS_SAME(decltype(d + *pi), I)],
- int[RANGES_IS_SAME(decltype(*pi - *pi), decltype(d))],
- int[RANGES_IS_SAME(decltype((*pi)[d]), decltype(**pi))],
- decltype(*pi < *pi ? true : false),
- decltype(*pi > *pi ? true : false),
- decltype(*pi <= *pi ? true : false),
- decltype(*pi >= *pi ? true : false)
- > * = nullptr)
- {
- return std::random_access_iterator_tag{};
- }
-
- template<typename I>
- auto cpp17_iterator_category_3_(long)
- {
- return std::forward_iterator_tag{};
- }
- // Satisfies Cpp17BidirectionalIterator?
- template<typename I>
- auto cpp17_iterator_category_3_(
- int,
- I *pi = nullptr,
- void (*fn)(I const &) = nullptr,
- always_<
- void,
- decltype(fn((*pi)--)), // i-- convertible to I const &
- int[RANGES_IS_SAME(decltype(--*pi), I &)], // --i has type I &
- // *i has the same type as *i--
- int[RANGES_IS_SAME(decltype(**pi), decltype(*(*pi)--))]
- > * = nullptr)
- {
- return cpp17_iterator_category_4_<I>(0);
- }
-
- template<typename I>
- auto cpp17_iterator_category_2_(long)
- {
- return std::input_iterator_tag{};
- }
- // Satisfies Cpp17ForwardIterator?
- template<typename I>
- auto cpp17_iterator_category_2_(
- int,
- I *pi = nullptr,
- void (*fn)(I const &) = nullptr,
- typename readable_traits<I>::value_type *pv = nullptr,
- typename readable_traits<I>::value_type const *pcv = nullptr,
- always_<
- void,
- decltype(I{}), // Default constructible
- decltype(fn((*pi)++)), // i++ convertible to I const &
- // *i has the same type as *i++
- int[RANGES_IS_SAME(decltype(**pi), decltype(*(*pi)++))],
- // *i is a real reference to value_type
- #ifdef RANGES_WORKAROUND_MSVC_793042
- enable_if_t<RANGES_IS_SAME(decltype(**pi), decltype(*pv)) ||
- RANGES_IS_SAME(decltype(**pi), decltype(*pcv)) ||
- RANGES_IS_SAME(decltype(**pi), typename readable_traits<I>::value_type &&) ||
- RANGES_IS_SAME(decltype(**pi), typename readable_traits<I>::value_type const &&)>
- #else // ^^^ workaround / no workaround vvv
- int[RANGES_IS_SAME(decltype(**pi), decltype(*pv)) ||
- RANGES_IS_SAME(decltype(**pi), decltype(*pcv)) ||
- RANGES_IS_SAME(decltype(**pi), typename readable_traits<I>::value_type &&) ||
- RANGES_IS_SAME(decltype(**pi), typename readable_traits<I>::value_type const &&)]
- #endif // RANGES_WORKAROUND_MSVC_793042
- > * = nullptr)
- {
- return cpp17_iterator_category_3_<I>(0);
- }
-
- template<typename I>
- using cpp17_readable_iterator_category_t =
- decltype(detail::cpp17_iterator_category_2_<I>(0));
-
- template<typename I>
- auto cpp17_iterator_category_(long)
- {
- return cpp17_iterator_category_2_<I>(0);
- }
- // Explicitly declares its category?
- template<typename I>
- typename I::iterator_category cpp17_iterator_category_(int)
- {
- return {};
- }
-
- template<typename I>
- auto std_iterator_traits_impl_2_(long)
- {
- return std_output_iterator_traits<
- decltype(detail::cpp17_difference_type_<I>(0))>{};
- }
- // Satisfies Cpp17InputIterator?
- template<typename I>
- auto std_iterator_traits_impl_2_(
- int,
- I *pi = nullptr,
- typename incrementable_traits<I>::difference_type d = 0,
- typename readable_traits<I>::value_type const *pcv = nullptr,
- always_<
- void,
- int[decltype(d)(-1) < decltype(d)(0)], // signed difference type
- decltype(decltype(*pcv)(**pi)), // sensible reference/value type
- decltype(decltype(*pcv)(*(*pi)++)), // sensible post-increment result
- decltype(*pi == *pi ? true : false), // equality comparable
- decltype(*pi != *pi ? true : false) // " "
- > * = nullptr)
- {
- using D = typename incrementable_traits<I>::difference_type;
- struct yes_traits
- {
- using difference_type = D;
- using value_type = typename readable_traits<I>::value_type;
- using reference = decltype(cpp17_reference_type_<I>(0));
- using pointer = decltype(cpp17_pointer_type_<I>(0));
- using iterator_category = decltype(cpp17_iterator_category_<I>(0));
- };
- struct no_traits
- {};
- return if_then_t<is_integral_<D>(0), yes_traits, no_traits>{};
- }
-
- template<typename I>
- nil_ std_iterator_traits_impl_(long)
- {
- return {};
- }
- // Satisfies Cpp17Iterator?
- template<typename I>
- auto std_iterator_traits_impl_(
- int,
- I *pi = nullptr,
- void (*nv)(...) = nullptr,
- always_<
- void,
- decltype(nv(**pi)),
- int[RANGES_IS_SAME(decltype(++*pi), I &)],
- decltype(nv(*(*pi)++))
- > * = nullptr)
- {
- return std_iterator_traits_impl_2_<I>(0);
- }
-
- template<typename T>
- constexpr bool has_iterator_typedefs_impl_(
- int,
- always_<
- void,
- typename T::difference_type,
- typename T::value_type,
- typename T::pointer,
- typename T::reference,
- typename T::iterator_category
- > * = nullptr)
- {
- return true;
- }
- template<typename T>
- constexpr bool has_iterator_typedefs_impl_(long)
- {
- return false;
- }
- }
- /// \endcond
- }
-
- // Hijack the primary std::iterator_traits template from each of the 3 major
- // standard library implementations
- RANGES_BEGIN_NAMESPACE_STD
- RANGES_BEGIN_NAMESPACE_VERSION
- #if defined(__GLIBCXX__)
- template<typename I>
- struct __iterator_traits<
- I,
- ::ranges::detail::enable_if_t<!::ranges::detail::has_iterator_typedefs_impl_<I>(0)>>
- : decltype(::ranges::detail::std_iterator_traits_impl_<I>(0))
- {};
- #elif defined(_LIBCPP_VERSION)
- template<typename I>
- struct __iterator_traits<I, false> // doesn't have I::iterator_category
- : decltype(::ranges::detail::std_iterator_traits_impl_<I>(0))
- {};
- #elif defined(_MSVC_STL_VERSION)
- template<typename I>
- struct _Iterator_traits_base<
- I,
- #ifdef RANGES_WORKAROUND_MSVC_792338
- ::ranges::detail::enable_if_t<decltype(bool_constant<
- !::ranges::detail::has_iterator_typedefs_impl_<I>(0)>{})::value>>
- #else // ^^^ workaround / no workaround vvv
- ::ranges::detail::enable_if_t<!::ranges::detail::has_iterator_typedefs_impl_<I>(0)>>
- #endif // RANGES_WORKAROUND_MSVC_792338
- : decltype(::ranges::detail::std_iterator_traits_impl_<I>(0))
- {};
- #endif
- RANGES_END_NAMESPACE_VERSION
- RANGES_END_NAMESPACE_STD
-
- #endif // RANGES_DEEP_STL_INTEGRATION
-
- #endif // RANGES_V3_STD_ITERATOR
|