Warning, /include/std/iterator is written in an unsupported language. File is not indexed.
0001 // Range v3 library
0002 //
0003 // Copyright Eric Niebler 2018-present
0004 //
0005 // Use, modification and distribution is subject to the
0006 // Boost Software License, Version 1.0. (See accompanying
0007 // file LICENSE_1_0.txt or copy at
0008 // http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 // Project home: https://github.com/ericniebler/range-v3
0011 //
0012
0013 #ifndef RANGES_V3_STD_ITERATOR
0014 #define RANGES_V3_STD_ITERATOR
0015
0016 #if defined(__GNUC__)
0017 #include_next <iterator>
0018 #elif defined(_MSC_VER)
0019 #include <../include/iterator> // HACKHACK
0020 #else
0021 #error "Cannot use range-v3 STL deep integration on this platform."
0022 #endif
0023
0024 #if RANGES_DEEP_STL_INTEGRATION
0025
0026 #include <range/v3/detail/config.hpp>
0027 #include <std/detail/associated_types.hpp>
0028
0029 #include <range/v3/detail/prologue.hpp>
0030
0031 namespace ranges
0032 {
0033 template<typename I>
0034 struct incrementable_traits;
0035
0036 template<typename I>
0037 struct indirectly_readable_traits;
0038
0039 /// \cond
0040 namespace detail
0041 {
0042 template<typename I>
0043 typename incrementable_traits<I>::difference_type cpp17_difference_type_(int);
0044 template<typename I>
0045 void cpp17_difference_type_(long);
0046
0047 template<typename I>
0048 typename I::pointer cpp17_pointer_type_(int);
0049 template<typename I>
0050 auto cpp17_pointer_type_(long, I *pi = nullptr) -> decltype(pi->operator->());
0051 template<typename I>
0052 void cpp17_pointer_type_(...);
0053
0054 template<typename I>
0055 typename I::reference cpp17_reference_type_(int);
0056 template<typename I>
0057 auto cpp17_reference_type_(long, I *pi = nullptr) -> decltype(**pi);
0058
0059 template<typename I>
0060 auto cpp17_iterator_category_4_(long)
0061 {
0062 return std::bidirectional_iterator_tag{};
0063 }
0064 // Satisfies Cpp17RandomAccessIterator?
0065 template<typename I>
0066 auto cpp17_iterator_category_4_(
0067 int,
0068 I *pi = nullptr,
0069 typename incrementable_traits<I>::difference_type d = 0,
0070 always_<
0071 void,
0072 int[RANGES_IS_SAME(decltype(*pi += d), I &)],
0073 int[RANGES_IS_SAME(decltype(*pi -= d), I &)],
0074 int[RANGES_IS_SAME(decltype(*pi + d), I)],
0075 int[RANGES_IS_SAME(decltype(*pi - d), I)],
0076 int[RANGES_IS_SAME(decltype(d + *pi), I)],
0077 int[RANGES_IS_SAME(decltype(*pi - *pi), decltype(d))],
0078 int[RANGES_IS_SAME(decltype((*pi)[d]), decltype(**pi))],
0079 decltype(*pi < *pi ? true : false),
0080 decltype(*pi > *pi ? true : false),
0081 decltype(*pi <= *pi ? true : false),
0082 decltype(*pi >= *pi ? true : false)
0083 > * = nullptr)
0084 {
0085 return std::random_access_iterator_tag{};
0086 }
0087
0088 template<typename I>
0089 auto cpp17_iterator_category_3_(long)
0090 {
0091 return std::forward_iterator_tag{};
0092 }
0093 // Satisfies Cpp17BidirectionalIterator?
0094 template<typename I>
0095 auto cpp17_iterator_category_3_(
0096 int,
0097 I *pi = nullptr,
0098 void (*fn)(I const &) = nullptr,
0099 always_<
0100 void,
0101 decltype(fn((*pi)--)), // i-- convertible to I const &
0102 int[RANGES_IS_SAME(decltype(--*pi), I &)], // --i has type I &
0103 // *i has the same type as *i--
0104 int[RANGES_IS_SAME(decltype(**pi), decltype(*(*pi)--))]
0105 > * = nullptr)
0106 {
0107 return cpp17_iterator_category_4_<I>(0);
0108 }
0109
0110 template<typename I>
0111 auto cpp17_iterator_category_2_(long)
0112 {
0113 return std::input_iterator_tag{};
0114 }
0115 // Satisfies Cpp17ForwardIterator?
0116 template<typename I>
0117 auto cpp17_iterator_category_2_(
0118 int,
0119 I *pi = nullptr,
0120 void (*fn)(I const &) = nullptr,
0121 typename indirectly_readable_traits<I>::value_type *pv = nullptr,
0122 typename indirectly_readable_traits<I>::value_type const *pcv = nullptr,
0123 always_<
0124 void,
0125 decltype(I{}), // Default constructible
0126 decltype(fn((*pi)++)), // i++ convertible to I const &
0127 // *i has the same type as *i++
0128 int[RANGES_IS_SAME(decltype(**pi), decltype(*(*pi)++))],
0129 // *i is a real reference to value_type
0130 #ifdef RANGES_WORKAROUND_MSVC_793042
0131 enable_if_t<RANGES_IS_SAME(decltype(**pi), decltype(*pv)) ||
0132 RANGES_IS_SAME(decltype(**pi), decltype(*pcv)) ||
0133 RANGES_IS_SAME(decltype(**pi), typename indirectly_readable_traits<I>::value_type &&) ||
0134 RANGES_IS_SAME(decltype(**pi), typename indirectly_readable_traits<I>::value_type const &&)>
0135 #else // ^^^ workaround / no workaround vvv
0136 int[RANGES_IS_SAME(decltype(**pi), decltype(*pv)) ||
0137 RANGES_IS_SAME(decltype(**pi), decltype(*pcv)) ||
0138 RANGES_IS_SAME(decltype(**pi), typename indirectly_readable_traits<I>::value_type &&) ||
0139 RANGES_IS_SAME(decltype(**pi), typename indirectly_readable_traits<I>::value_type const &&)]
0140 #endif // RANGES_WORKAROUND_MSVC_793042
0141 > * = nullptr)
0142 {
0143 return cpp17_iterator_category_3_<I>(0);
0144 }
0145
0146 template<typename I>
0147 using cpp17_readable_iterator_category_t =
0148 decltype(detail::cpp17_iterator_category_2_<I>(0));
0149
0150 template<typename I>
0151 auto cpp17_iterator_category_(long)
0152 {
0153 return cpp17_iterator_category_2_<I>(0);
0154 }
0155 // Explicitly declares its category?
0156 template<typename I>
0157 typename I::iterator_category cpp17_iterator_category_(int)
0158 {
0159 return {};
0160 }
0161
0162 template<typename I>
0163 auto std_iterator_traits_impl_2_(long)
0164 {
0165 return std_output_iterator_traits<
0166 decltype(detail::cpp17_difference_type_<I>(0))>{};
0167 }
0168 // Satisfies Cpp17InputIterator?
0169 template<typename I>
0170 auto std_iterator_traits_impl_2_(
0171 int,
0172 I *pi = nullptr,
0173 typename incrementable_traits<I>::difference_type d = 0,
0174 typename indirectly_readable_traits<I>::value_type const *pcv = nullptr,
0175 always_<
0176 void,
0177 int[decltype(d)(-1) < decltype(d)(0)], // signed difference type
0178 decltype(decltype(*pcv)(**pi)), // sensible reference/value type
0179 decltype(decltype(*pcv)(*(*pi)++)), // sensible post-increment result
0180 decltype(*pi == *pi ? true : false), // equality comparable
0181 decltype(*pi != *pi ? true : false) // " "
0182 > * = nullptr)
0183 {
0184 using D = typename incrementable_traits<I>::difference_type;
0185 struct yes_traits
0186 {
0187 using difference_type = D;
0188 using value_type = typename indirectly_readable_traits<I>::value_type;
0189 using reference = decltype(cpp17_reference_type_<I>(0));
0190 using pointer = decltype(cpp17_pointer_type_<I>(0));
0191 using iterator_category = decltype(cpp17_iterator_category_<I>(0));
0192 };
0193 struct no_traits
0194 {};
0195 return conditional_t<is_integral_<D>(0), yes_traits, no_traits>{};
0196 }
0197
0198 template<typename I>
0199 nil_ std_iterator_traits_impl_(long)
0200 {
0201 return {};
0202 }
0203 // Satisfies Cpp17Iterator?
0204 template<typename I>
0205 auto std_iterator_traits_impl_(
0206 int,
0207 I *pi = nullptr,
0208 void (*nv)(...) = nullptr,
0209 always_<
0210 void,
0211 decltype(nv(**pi)),
0212 int[RANGES_IS_SAME(decltype(++*pi), I &)],
0213 decltype(nv(*(*pi)++))
0214 > * = nullptr)
0215 {
0216 return std_iterator_traits_impl_2_<I>(0);
0217 }
0218
0219 template<typename T>
0220 constexpr bool has_iterator_typedefs_impl_(
0221 int,
0222 always_<
0223 void,
0224 typename T::difference_type,
0225 typename T::value_type,
0226 typename T::pointer,
0227 typename T::reference,
0228 typename T::iterator_category
0229 > * = nullptr)
0230 {
0231 return true;
0232 }
0233 template<typename T>
0234 constexpr bool has_iterator_typedefs_impl_(long)
0235 {
0236 return false;
0237 }
0238 }
0239 /// \endcond
0240 } // namespace ranges
0241
0242 // Hijack the primary std::iterator_traits template from each of the 3 major
0243 // standard library implementations
0244 RANGES_BEGIN_NAMESPACE_STD
0245 RANGES_BEGIN_NAMESPACE_VERSION
0246 #if defined(__GLIBCXX__)
0247 template<typename I>
0248 struct __iterator_traits<
0249 I,
0250 ::ranges::detail::enable_if_t<!::ranges::detail::has_iterator_typedefs_impl_<I>(0)>>
0251 : decltype(::ranges::detail::std_iterator_traits_impl_<I>(0))
0252 {};
0253 #elif defined(_LIBCPP_VERSION)
0254 template<typename I>
0255 struct __iterator_traits<I, false> // doesn't have I::iterator_category
0256 : decltype(::ranges::detail::std_iterator_traits_impl_<I>(0))
0257 {};
0258 #elif defined(_MSVC_STL_VERSION)
0259 template<typename I>
0260 struct _Iterator_traits_base<
0261 I,
0262 #ifdef RANGES_WORKAROUND_MSVC_792338
0263 ::ranges::detail::enable_if_t<decltype(bool_constant<
0264 !::ranges::detail::has_iterator_typedefs_impl_<I>(0)>{})::value>>
0265 #else // ^^^ workaround / no workaround vvv
0266 ::ranges::detail::enable_if_t<!::ranges::detail::has_iterator_typedefs_impl_<I>(0)>>
0267 #endif // RANGES_WORKAROUND_MSVC_792338
0268 : decltype(::ranges::detail::std_iterator_traits_impl_<I>(0))
0269 {};
0270 #endif
0271 RANGES_END_NAMESPACE_VERSION
0272 RANGES_END_NAMESPACE_STD
0273
0274 #include <range/v3/detail/epilogue.hpp>
0275
0276 #endif // RANGES_DEEP_STL_INTEGRATION
0277
0278 #endif // RANGES_V3_STD_ITERATOR