Horizon
Loading...
Searching...
No Matches
associated_types.hpp
1// Range v3 library
2//
3// Copyright Eric Niebler 2013-2014, 2016-present
4// Copyright Casey Carter 2016
5//
6// Use, modification and distribution is subject to the
7// Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at
9// http://www.boost.org/LICENSE_1_0.txt)
10//
11// Project home: https://github.com/ericniebler/range-v3
12//
13
14#ifndef RANGES_V3_STD_DETAIL_ASSOCIATED_TYPES_HPP
15#define RANGES_V3_STD_DETAIL_ASSOCIATED_TYPES_HPP
16
17#include <climits>
18#include <cstdint>
19
20#include <range/v3/detail/config.hpp>
21
22#include <range/v3/detail/prologue.hpp>
23
24namespace ranges
25{
28
31 namespace detail
32 {
33 struct nil_
34 {};
35
36 template<typename T, typename...>
37 using always_ = T;
38
39#if defined(_MSC_VER) && !defined(__clang__) && !defined(__EDG__)
40 // MSVC laughs at your silly micro-optimizations and implements
41 // conditional_t, enable_if_t, is_object_v, and is_integral_v in the
42 // compiler.
43 using std::conditional_t;
44 using std::enable_if;
45 using std::enable_if_t;
46#else // ^^^ MSVC / not MSVC vvv
47 template<bool>
48 struct _cond
49 {
50 template<typename, typename U>
51 using invoke = U;
52 };
53 template<>
54 struct _cond<true>
55 {
56 template<typename T, typename>
57 using invoke = T;
58 };
59 template<bool B, typename T, typename U>
60 using conditional_t = typename _cond<B>::template invoke<T, U>;
61
62 template<bool>
63 struct enable_if
64 {};
65 template<>
66 struct enable_if<true>
67 {
68 template<typename T>
69 using invoke = T;
70 };
71 template<bool B, typename T = void>
72 using enable_if_t = typename enable_if<B>::template invoke<T>;
73
74#ifndef __clang__
75 // NB: insufficient for MSVC, which (non-conformingly) allows function
76 // pointers to implicitly convert to void*.
77 void is_objptr_(void const volatile *);
78
79 // std::is_object, optimized for compile time.
80 template<typename T>
81 constexpr bool is_object_(long)
82 {
83 return false;
84 }
85 template<typename T>
86 constexpr bool is_object_(int, T * (*q)(T &) = nullptr, T * p = nullptr,
87 decltype(detail::is_objptr_(q(*p))) * = nullptr)
88 {
89 return (void)p, (void)q, true;
90 }
91#endif // !__clang__
92
93 template<typename T>
94 constexpr bool is_integral_(...)
95 {
96 return false;
97 }
98 template<typename T, T = 1>
99 constexpr bool is_integral_(long)
100 {
101 return true;
102 }
103#if defined(__cpp_nontype_template_parameter_class) && \
104 __cpp_nontype_template_parameter_class > 0
105 template<typename T>
106 constexpr bool is_integral_(int, int T::* = nullptr)
107 {
108 return false;
109 }
110#endif
111#endif // detect MSVC
112
113 template<typename T>
114 struct with_difference_type_
115 {
116 using difference_type = T;
117 };
118
119 template<typename T>
120 using difference_result_t =
121 decltype(std::declval<T const &>() - std::declval<T const &>());
122
123 template<typename, typename = void>
124 struct incrementable_traits_2_
125 {};
126
127 template<typename T>
128 struct incrementable_traits_2_<
129 T,
130#if defined(_MSC_VER) && !defined(__clang__) && !defined(__EDG__)
131 std::enable_if_t<std::is_integral_v<difference_result_t<T>>>>
132#elif defined(RANGES_WORKAROUND_GCC_91923)
133 std::enable_if_t<std::is_integral<difference_result_t<T>>::value>>
134#else
135 always_<void, int[is_integral_<difference_result_t<T>>(0)]>>
136#endif // detect MSVC
137 {
138 using difference_type = std::make_signed_t<difference_result_t<T>>;
139 };
140
141 template<typename T, typename = void>
142 struct incrementable_traits_1_ : incrementable_traits_2_<T>
143 {};
144
145 template<typename T>
146 struct incrementable_traits_1_<T *>
147#ifdef __clang__
148 : conditional_t<__is_object(T), with_difference_type_<std::ptrdiff_t>, nil_>
149#elif defined(_MSC_VER) && !defined(__EDG__)
150 : conditional_t<std::is_object_v<T>, with_difference_type_<std::ptrdiff_t>, nil_>
151#else // ^^^ MSVC / not MSVC vvv
152 : conditional_t<is_object_<T>(0), with_difference_type_<std::ptrdiff_t>, nil_>
153#endif // detect MSVC
154 {};
155
156 template<typename T>
157 struct incrementable_traits_1_<T, always_<void, typename T::difference_type>>
158 {
159 using difference_type = typename T::difference_type;
160 };
161 } // namespace detail
163
164 template<typename T>
165 struct incrementable_traits : detail::incrementable_traits_1_<T>
166 {};
167
168 template<typename T>
170 {};
171
173 namespace detail
174 {
175#ifdef __clang__
176 template<typename T, bool = __is_object(T)>
177#elif defined(_MSC_VER) && !defined(__EDG__)
178 template<typename T, bool = std::is_object_v<T>>
179#else // ^^^ MSVC / not MSVC vvv
180 template<typename T, bool = is_object_<T>(0)>
181#endif // detect MSVC
182 struct with_value_type_
183 {};
184 template<typename T>
185 struct with_value_type_<T, true>
186 {
187 using value_type = T;
188 };
189 template<typename T>
190 struct with_value_type_<T const, true>
191 {
192 using value_type = T;
193 };
194 template<typename T>
195 struct with_value_type_<T volatile, true>
196 {
197 using value_type = T;
198 };
199 template<typename T>
200 struct with_value_type_<T const volatile, true>
201 {
202 using value_type = T;
203 };
204 template<typename, typename = void>
205 struct readable_traits_2_
206 {};
207 template<typename T>
208 struct readable_traits_2_<T, always_<void, typename T::element_type>>
209 : with_value_type_<typename T::element_type>
210 {};
211 template<typename T, typename = void>
212 struct readable_traits_1_ : readable_traits_2_<T>
213 {};
214 template<typename T>
215 struct readable_traits_1_<T[]> : with_value_type_<T>
216 {};
217 template<typename T, std::size_t N>
218 struct readable_traits_1_<T[N]> : with_value_type_<T>
219 {};
220 template<typename T>
221 struct readable_traits_1_<T *> : detail::with_value_type_<T>
222 {};
223 template<typename T>
224 struct readable_traits_1_<T, always_<void, typename T::value_type>>
225 : with_value_type_<typename T::value_type>
226 {};
227 } // namespace detail
229
231 // Not to spec:
232 // * For class types with both member value_type and element_type, value_type is
233 // preferred (see ericniebler/stl2#299).
234 template<typename T>
235 struct indirectly_readable_traits : detail::readable_traits_1_<T>
236 {};
237
238 template<typename T>
241
243 namespace detail
244 {
245 template<typename D = std::ptrdiff_t>
246 struct std_output_iterator_traits
247 {
248 using iterator_category = std::output_iterator_tag;
249 using difference_type = D;
250 using value_type = void;
251 using reference = void;
252 using pointer = void;
253 };
254
255 // For testing whether a particular instantiation of std::iterator_traits
256 // is user-specified or not.
257#if defined(_MSVC_STL_UPDATE) && defined(__cpp_lib_concepts) && _MSVC_STL_UPDATE >= 201908L
258 template<typename I>
259 inline constexpr bool is_std_iterator_traits_specialized_v =
260 !std::_Is_from_primary<std::iterator_traits<I>>;
261#else
262#if defined(__GLIBCXX__)
263 template<typename I>
264 char (&is_std_iterator_traits_specialized_impl_(std::__iterator_traits<I> *))[2];
265 template<typename I>
266 char is_std_iterator_traits_specialized_impl_(void *);
267#elif defined(_LIBCPP_VERSION)
268 // In older versions of libc++, the base template inherits from std::__iterator_traits<typename, bool>.
269 template<template<typename, bool> class IteratorTraitsBase, typename I, bool B>
270 char (&libcpp_iterator_traits_base_impl(IteratorTraitsBase<I, B> *))[2];
271 template<template<typename, bool> class IteratorTraitsBase, typename I>
272 char libcpp_iterator_traits_base_impl(void *);
273
274 // In newer versions, the base template has only one template parameter and provides the
275 // __primary_template typedef which aliases the iterator_traits specialization.
276 template<template<typename> class, typename I>
277 char (&libcpp_iterator_traits_base_impl(typename std::iterator_traits<I>::__primary_template *))[2];
278 template<template<typename> class, typename I>
279 char libcpp_iterator_traits_base_impl(void *);
280
281 template<typename I>
282 auto is_std_iterator_traits_specialized_impl_(std::iterator_traits<I>* traits)
283 -> decltype(libcpp_iterator_traits_base_impl<std::__iterator_traits, I>(traits));
284#elif defined(_MSVC_STL_VERSION)
285 template<typename I>
286 char (&is_std_iterator_traits_specialized_impl_(
287 std::_Iterator_traits_base<I> *))[2];
288 template<typename I>
289 char is_std_iterator_traits_specialized_impl_(void *);
290#else
291 template<typename I>
292 char (&is_std_iterator_traits_specialized_impl_(void *))[2];
293#endif
294 template<typename, typename T>
295 char (&is_std_iterator_traits_specialized_impl_(std::iterator_traits<T *> *))[2];
296
297 template<typename I>
298 RANGES_INLINE_VAR constexpr bool is_std_iterator_traits_specialized_v =
299 1 == sizeof(is_std_iterator_traits_specialized_impl_<I>(
300 static_cast<std::iterator_traits<I> *>(nullptr)));
301#endif
302 // The standard iterator_traits<T *> specialization(s) do not count
303 // as user-specialized. This will no longer be necessary in C++20.
304 // This helps with `T volatile*` and `void *`.
305 template<typename T>
306 RANGES_INLINE_VAR constexpr bool is_std_iterator_traits_specialized_v<T *> =
307 false;
308 } // namespace detail
310} // namespace ranges
311
312#include <range/v3/detail/epilogue.hpp>
313
314#endif
typename Fn::template invoke< Args... > invoke
Evaluate the invocable Fn with the arguments Args.
Definition meta.hpp:541
typename detail::_cond< If >::template invoke< Then, Else > conditional_t
Select one type or another depending on a compile-time Boolean.
Definition meta.hpp:1148
Definition associated_types.hpp:166
Definition associated_types.hpp:236