Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:12:44

0001 // Range v3 library
0002 //
0003 //  Copyright Eric Niebler 2013-2014, 2016-present
0004 //  Copyright Casey Carter 2016
0005 //
0006 //  Use, modification and distribution is subject to the
0007 //  Boost Software License, Version 1.0. (See accompanying
0008 //  file LICENSE_1_0.txt or copy at
0009 //  http://www.boost.org/LICENSE_1_0.txt)
0010 //
0011 // Project home: https://github.com/ericniebler/range-v3
0012 //
0013 
0014 #ifndef RANGES_V3_STD_DETAIL_ASSOCIATED_TYPES_HPP
0015 #define RANGES_V3_STD_DETAIL_ASSOCIATED_TYPES_HPP
0016 
0017 #include <climits>
0018 #include <cstdint>
0019 
0020 #include <range/v3/detail/config.hpp>
0021 
0022 #include <range/v3/detail/prologue.hpp>
0023 
0024 namespace ranges
0025 {
0026     /// \addtogroup group-iterator
0027     /// @{
0028 
0029     ////////////////////////////////////////////////////////////////////////////////////////
0030     /// \cond
0031     namespace detail
0032     {
0033         struct nil_
0034         {};
0035 
0036         template<typename T, typename...>
0037         using always_ = T;
0038 
0039 #if defined(_MSC_VER) && !defined(__clang__) && !defined(__EDG__)
0040         // MSVC laughs at your silly micro-optimizations and implements
0041         // conditional_t, enable_if_t, is_object_v, and is_integral_v in the
0042         // compiler.
0043         using std::conditional_t;
0044         using std::enable_if;
0045         using std::enable_if_t;
0046 #else  // ^^^ MSVC / not MSVC vvv
0047         template<bool>
0048         struct _cond
0049         {
0050             template<typename, typename U>
0051             using invoke = U;
0052         };
0053         template<>
0054         struct _cond<true>
0055         {
0056             template<typename T, typename>
0057             using invoke = T;
0058         };
0059         template<bool B, typename T, typename U>
0060         using conditional_t = typename _cond<B>::template invoke<T, U>;
0061 
0062         template<bool>
0063         struct enable_if
0064         {};
0065         template<>
0066         struct enable_if<true>
0067         {
0068             template<typename T>
0069             using invoke = T;
0070         };
0071         template<bool B, typename T = void>
0072         using enable_if_t = typename enable_if<B>::template invoke<T>;
0073 
0074 #ifndef __clang__
0075         // NB: insufficient for MSVC, which (non-conformingly) allows function
0076         // pointers to implicitly convert to void*.
0077         void is_objptr_(void const volatile *);
0078 
0079         // std::is_object, optimized for compile time.
0080         template<typename T>
0081         constexpr bool is_object_(long)
0082         {
0083             return false;
0084         }
0085         template<typename T>
0086         constexpr bool is_object_(int, T * (*q)(T &) = nullptr, T * p = nullptr,
0087                                   decltype(detail::is_objptr_(q(*p))) * = nullptr)
0088         {
0089             return (void)p, (void)q, true;
0090         }
0091 #endif // !__clang__
0092 
0093         template<typename T>
0094         constexpr bool is_integral_(...)
0095         {
0096             return false;
0097         }
0098         template<typename T, T = 1>
0099         constexpr bool is_integral_(long)
0100         {
0101             return true;
0102         }
0103 #if defined(__cpp_nontype_template_parameter_class) && \
0104     __cpp_nontype_template_parameter_class > 0
0105         template<typename T>
0106         constexpr bool is_integral_(int, int T::* = nullptr)
0107         {
0108             return false;
0109         }
0110 #endif
0111 #endif // detect MSVC
0112 
0113         template<typename T>
0114         struct with_difference_type_
0115         {
0116             using difference_type = T;
0117         };
0118 
0119         template<typename T>
0120         using difference_result_t =
0121             decltype(std::declval<T const &>() - std::declval<T const &>());
0122 
0123         template<typename, typename = void>
0124         struct incrementable_traits_2_
0125         {};
0126 
0127         template<typename T>
0128         struct incrementable_traits_2_<
0129             T,
0130 #if defined(_MSC_VER) && !defined(__clang__) && !defined(__EDG__)
0131             std::enable_if_t<std::is_integral_v<difference_result_t<T>>>>
0132 #elif defined(RANGES_WORKAROUND_GCC_91923)
0133             std::enable_if_t<std::is_integral<difference_result_t<T>>::value>>
0134 #else
0135             always_<void, int[is_integral_<difference_result_t<T>>(0)]>>
0136 #endif // detect MSVC
0137         {
0138             using difference_type = std::make_signed_t<difference_result_t<T>>;
0139         };
0140 
0141         template<typename T, typename = void>
0142         struct incrementable_traits_1_ : incrementable_traits_2_<T>
0143         {};
0144 
0145         template<typename T>
0146         struct incrementable_traits_1_<T *>
0147 #ifdef __clang__
0148           : conditional_t<__is_object(T), with_difference_type_<std::ptrdiff_t>, nil_>
0149 #elif defined(_MSC_VER) && !defined(__EDG__)
0150           : conditional_t<std::is_object_v<T>, with_difference_type_<std::ptrdiff_t>, nil_>
0151 #else // ^^^ MSVC / not MSVC vvv
0152           : conditional_t<is_object_<T>(0), with_difference_type_<std::ptrdiff_t>, nil_>
0153 #endif // detect MSVC
0154         {};
0155 
0156         template<typename T>
0157         struct incrementable_traits_1_<T, always_<void, typename T::difference_type>>
0158         {
0159             using difference_type = typename T::difference_type;
0160         };
0161     } // namespace detail
0162     /// \endcond
0163 
0164     template<typename T>
0165     struct incrementable_traits : detail::incrementable_traits_1_<T>
0166     {};
0167 
0168     template<typename T>
0169     struct incrementable_traits<T const> : incrementable_traits<T>
0170     {};
0171 
0172     /// \cond
0173     namespace detail
0174     {
0175 #ifdef __clang__
0176         template<typename T, bool = __is_object(T)>
0177 #elif defined(_MSC_VER) && !defined(__EDG__)
0178         template<typename T, bool = std::is_object_v<T>>
0179 #else // ^^^ MSVC / not MSVC vvv
0180         template<typename T, bool = is_object_<T>(0)>
0181 #endif // detect MSVC
0182         struct with_value_type_
0183         {};
0184         template<typename T>
0185         struct with_value_type_<T, true>
0186         {
0187             using value_type = T;
0188         };
0189         template<typename T>
0190         struct with_value_type_<T const, true>
0191         {
0192             using value_type = T;
0193         };
0194         template<typename T>
0195         struct with_value_type_<T volatile, true>
0196         {
0197             using value_type = T;
0198         };
0199         template<typename T>
0200         struct with_value_type_<T const volatile, true>
0201         {
0202             using value_type = T;
0203         };
0204         template<typename, typename = void>
0205         struct readable_traits_2_
0206         {};
0207         template<typename T>
0208         struct readable_traits_2_<T, always_<void, typename T::element_type>>
0209           : with_value_type_<typename T::element_type>
0210         {};
0211         template<typename T, typename = void>
0212         struct readable_traits_1_ : readable_traits_2_<T>
0213         {};
0214         template<typename T>
0215         struct readable_traits_1_<T[]> : with_value_type_<T>
0216         {};
0217         template<typename T, std::size_t N>
0218         struct readable_traits_1_<T[N]> : with_value_type_<T>
0219         {};
0220         template<typename T>
0221         struct readable_traits_1_<T *> : detail::with_value_type_<T>
0222         {};
0223         template<typename T>
0224         struct readable_traits_1_<T, always_<void, typename T::value_type>>
0225           : with_value_type_<typename T::value_type>
0226         {};
0227     } // namespace detail
0228     /// \endcond
0229 
0230     ////////////////////////////////////////////////////////////////////////////////////////
0231     // Not to spec:
0232     // * For class types with both member value_type and element_type, value_type is
0233     //   preferred (see ericniebler/stl2#299).
0234     template<typename T>
0235     struct indirectly_readable_traits : detail::readable_traits_1_<T>
0236     {};
0237 
0238     template<typename T>
0239     struct indirectly_readable_traits<T const> : indirectly_readable_traits<T>
0240     {};
0241 
0242     /// \cond
0243     namespace detail
0244     {
0245         template<typename D = std::ptrdiff_t>
0246         struct std_output_iterator_traits
0247         {
0248             using iterator_category = std::output_iterator_tag;
0249             using difference_type = D;
0250             using value_type = void;
0251             using reference = void;
0252             using pointer = void;
0253         };
0254 
0255         // For testing whether a particular instantiation of std::iterator_traits
0256         // is user-specified or not.
0257 #if defined(_MSVC_STL_UPDATE) && defined(__cpp_lib_concepts) && _MSVC_STL_UPDATE >= 201908L
0258         template<typename I>
0259         inline constexpr bool is_std_iterator_traits_specialized_v =
0260             !std::_Is_from_primary<std::iterator_traits<I>>;
0261 #else
0262 #if defined(__GLIBCXX__)
0263         template<typename I>
0264         char (&is_std_iterator_traits_specialized_impl_(std::__iterator_traits<I> *))[2];
0265         template<typename I>
0266         char is_std_iterator_traits_specialized_impl_(void *);
0267 #elif defined(_LIBCPP_VERSION)
0268         // In older versions of libc++, the base template inherits from std::__iterator_traits<typename, bool>.
0269         template<template<typename, bool> class IteratorTraitsBase, typename I, bool B>
0270         char (&libcpp_iterator_traits_base_impl(IteratorTraitsBase<I, B> *))[2];
0271         template<template<typename, bool> class IteratorTraitsBase, typename I>
0272         char libcpp_iterator_traits_base_impl(void *);
0273 
0274         // In newer versions, the base template has only one template parameter and provides the
0275         // __primary_template typedef which aliases the iterator_traits specialization.
0276         template<template<typename> class, typename I>
0277         char (&libcpp_iterator_traits_base_impl(typename std::iterator_traits<I>::__primary_template *))[2];
0278         template<template<typename> class, typename I>
0279         char libcpp_iterator_traits_base_impl(void *);
0280 
0281         template<typename I>
0282         auto is_std_iterator_traits_specialized_impl_(std::iterator_traits<I>* traits)
0283             -> decltype(libcpp_iterator_traits_base_impl<std::__iterator_traits, I>(traits));
0284 #elif defined(_MSVC_STL_VERSION)
0285         template<typename I>
0286         char (&is_std_iterator_traits_specialized_impl_(
0287             std::_Iterator_traits_base<I> *))[2];
0288         template<typename I>
0289         char is_std_iterator_traits_specialized_impl_(void *);
0290 #else
0291         template<typename I>
0292         char (&is_std_iterator_traits_specialized_impl_(void *))[2];
0293 #endif
0294         template<typename, typename T>
0295         char (&is_std_iterator_traits_specialized_impl_(std::iterator_traits<T *> *))[2];
0296 
0297         template<typename I>
0298         RANGES_INLINE_VAR constexpr bool is_std_iterator_traits_specialized_v =
0299             1 == sizeof(is_std_iterator_traits_specialized_impl_<I>(
0300                      static_cast<std::iterator_traits<I> *>(nullptr)));
0301 #endif
0302         // The standard iterator_traits<T *> specialization(s) do not count
0303         // as user-specialized. This will no longer be necessary in C++20.
0304         // This helps with `T volatile*` and `void *`.
0305         template<typename T>
0306         RANGES_INLINE_VAR constexpr bool is_std_iterator_traits_specialized_v<T *> =
0307             false;
0308     } // namespace detail
0309     /// \endcond
0310 } // namespace ranges
0311 
0312 #include <range/v3/detail/epilogue.hpp>
0313 
0314 #endif