Horizon
Loading...
Searching...
No Matches
type_traits.hpp
Go to the documentation of this file.
1
2// Concepts library
3//
4// Copyright Eric Niebler 2013-present
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#ifndef CPP_TYPE_TRAITS_HPP
14#define CPP_TYPE_TRAITS_HPP
15
16#include <tuple>
17#include <utility>
18#include <type_traits>
19#include <meta/meta.hpp>
20
21namespace concepts
22{
23 template<typename T>
24 using remove_cvref_t =
25 typename std::remove_cv<
26 typename std::remove_reference<T>::type>::type;
27
29 namespace detail
30 {
31 template<typename From, typename To>
32 using is_convertible = std::is_convertible<meta::_t<std::add_rvalue_reference<From>>, To>;
33
34 template<bool>
35 struct if_else_
36 {
37 template<typename, typename U>
38 using invoke = U;
39 };
40 template<>
41 struct if_else_<true>
42 {
43 template<typename T, typename>
44 using invoke = T;
45 };
46 template<bool B, typename T, typename U>
47 using if_else_t = meta::invoke<if_else_<B>, T, U>;
48
49 template<bool>
50 struct if_
51 {};
52 template<>
53 struct if_<true>
54 {
55 template<typename T>
56 using invoke = T;
57 };
58 template<bool B, typename T = void>
59 using if_t = meta::invoke<if_<B>, T>;
60
61 template<typename From, typename To>
62 struct _copy_cv_
63 {
64 using type = To;
65 };
66 template<typename From, typename To>
67 struct _copy_cv_<From const, To>
68 {
69 using type = To const;
70 };
71 template<typename From, typename To>
72 struct _copy_cv_<From volatile, To>
73 {
74 using type = To volatile;
75 };
76 template<typename From, typename To>
77 struct _copy_cv_<From const volatile, To>
78 {
79 using type = To const volatile;
80 };
81 template<typename From, typename To>
82 using _copy_cv = meta::_t<_copy_cv_<From, To>>;
83
85 template<typename T, typename U, typename = void>
86 struct _builtin_common;
87
88 template<typename T, typename U>
89 using _builtin_common_t = meta::_t<_builtin_common<T, U>>;
90
91 template<typename T, typename U>
92 using _cond_res = decltype(true ? std::declval<T>() : std::declval<U>());
93
94 template<typename T, typename U, typename R = _builtin_common_t<T &, U &>>
95 using _rref_res =
96 if_else_t<std::is_reference<R>::value, meta::_t<std::remove_reference<R>> &&, R>;
97
98 template<typename T, typename U>
99 using _lref_res = _cond_res<_copy_cv<T, U> &, _copy_cv<U, T> &>;
100
101 template<typename T>
102 struct as_cref_
103 {
104 using type = T const &;
105 };
106 template<typename T>
107 struct as_cref_<T &>
108 {
109 using type = T const &;
110 };
111 template<typename T>
112 struct as_cref_<T &&>
113 {
114 using type = T const &;
115 };
116 template<>
117 struct as_cref_<void>
118 {
119 using type = void;
120 };
121 template<>
122 struct as_cref_<void const>
123 {
124 using type = void const;
125 };
126
127 template<typename T>
128 using as_cref_t = typename as_cref_<T>::type;
129
130 template<typename T>
131 using decay_t = typename std::decay<T>::type;
132
133 #if !defined(__GNUC__) || defined(__clang__)
134 template<typename T, typename U, typename = void>
135 struct _builtin_common_3
136 {};
137 template<typename T, typename U>
138 struct _builtin_common_3<T, U, meta::void_<_cond_res<as_cref_t<T>, as_cref_t<U>>>>
139 : std::decay<_cond_res<as_cref_t<T>, as_cref_t<U>>>
140 {};
141 template<typename T, typename U, typename = void>
142 struct _builtin_common_2
143 : _builtin_common_3<T, U>
144 {};
145 template<typename T, typename U>
146 struct _builtin_common_2<T, U, meta::void_<_cond_res<T, U>>>
147 : std::decay<_cond_res<T, U>>
148 {};
149 template<typename T, typename U, typename /* = void */>
150 struct _builtin_common
151 : _builtin_common_2<T, U>
152 {};
153 template<typename T, typename U>
154 struct _builtin_common<T &&, U &&, if_t<
155 is_convertible<T &&, _rref_res<T, U>>::value &&
156 is_convertible<U &&, _rref_res<T, U>>::value>>
157 {
158 using type = _rref_res<T, U>;
159 };
160 template<typename T, typename U>
161 struct _builtin_common<T &, U &>
163 {};
164 template<typename T, typename U>
165 struct _builtin_common<T &, U &&, if_t<
166 is_convertible<U &&, _builtin_common_t<T &, U const &>>::value>>
167 : _builtin_common<T &, U const &>
168 {};
169 template<typename T, typename U>
170 struct _builtin_common<T &&, U &>
171 : _builtin_common<U &, T &&>
172 {};
173 #else
174 template<typename T, typename U, typename = void>
175 struct _builtin_common_3
176 {};
177 template<typename T, typename U>
178 struct _builtin_common_3<T, U, meta::void_<_cond_res<as_cref_t<T>, as_cref_t<U>>>>
179 : std::decay<_cond_res<as_cref_t<T>, as_cref_t<U>>>
180 {};
181 template<typename T, typename U, typename = void>
182 struct _builtin_common_2
183 : _builtin_common_3<T, U>
184 {};
185 template<typename T, typename U>
186 struct _builtin_common_2<T, U, meta::void_<_cond_res<T, U>>>
187 : std::decay<_cond_res<T, U>>
188 {};
189 template<typename T, typename U, typename /* = void */>
190 struct _builtin_common
191 : _builtin_common_2<T, U>
192 {};
193 template<typename T, typename U, typename = void>
194 struct _builtin_common_rr
195 : _builtin_common_2<T &&, U &&>
196 {};
197 template<typename T, typename U>
198 struct _builtin_common_rr<T, U, if_t<
199 is_convertible<T &&, _rref_res<T, U>>::value &&
200 is_convertible<U &&, _rref_res<T, U>>::value>>
201 {
202 using type = _rref_res<T, U>;
203 };
204 template<typename T, typename U>
205 struct _builtin_common<T &&, U &&>
206 : _builtin_common_rr<T, U>
207 {};
208 template<typename T, typename U>
209 struct _builtin_common<T &, U &>
211 {};
212 template<typename T, typename U, typename = void>
213 struct _builtin_common_lr
214 : _builtin_common_2<T &, T &&>
215 {};
216 template<typename T, typename U>
217 struct _builtin_common_lr<T, U, if_t<
218 is_convertible<U &&, _builtin_common_t<T &, U const &>>::value>>
219 : _builtin_common<T &, U const &>
220 {};
221 template<typename T, typename U>
222 struct _builtin_common<T &, U &&>
223 : _builtin_common_lr<T, U>
224 {};
225 template<typename T, typename U>
226 struct _builtin_common<T &&, U &>
227 : _builtin_common<U &, T &&>
228 {};
229 #endif
230 }
232
236
240 template<typename ...Ts>
242 {};
243
244 template<typename T>
245 struct common_type<T>
246 : std::decay<T>
247 {};
248
249 template<typename T, typename U>
250 struct common_type<T, U>
251 : detail::if_else_t<
252 (META_IS_SAME(detail::decay_t<T>, T) &&
253 META_IS_SAME(detail::decay_t<U>, U) ),
254 meta::defer<detail::_builtin_common_t, T, U>,
255 common_type<detail::decay_t<T>, detail::decay_t<U>>>
256 {};
257
258 template<typename... Ts>
259 using common_type_t = typename common_type<Ts...>::type;
260
261 template<typename T, typename U, typename... Vs>
262 struct common_type<T, U, Vs...>
263 : meta::lazy::fold<meta::list<U, Vs...>, T, meta::quote<common_type_t>>
264 {};
265
267
271
274 template<
275 typename T,
276 typename U,
277 template<typename> class TQual,
278 template<typename> class UQual>
281
283 namespace detail
284 {
285 using _rref =
287 using _lref =
289
290 template<typename>
291 struct _xref
292 {
293 template<typename T>
294 using invoke = T;
295 };
296 template<typename T>
297 struct _xref<T &&>
298 {
299 template<typename U>
300 using invoke =
302 };
303 template<typename T>
304 struct _xref<T &>
305 {
306 template<typename U>
307 using invoke =
309 };
310 template<typename T>
311 struct _xref<T const>
312 {
313 template<typename U>
314 using invoke = U const;
315 };
316 template<typename T>
317 struct _xref<T volatile>
318 {
319 template<typename U>
320 using invoke = U volatile;
321 };
322 template<typename T>
323 struct _xref<T const volatile>
324 {
325 template<typename U>
326 using invoke = U const volatile;
327 };
328
329 template<typename T, typename U>
330 using _basic_common_reference =
331 basic_common_reference<
332 remove_cvref_t<T>,
333 remove_cvref_t<U>,
334 _xref<T>::template invoke,
335 _xref<U>::template invoke>;
336
337 template<typename T, typename U, typename = void>
338 struct _common_reference2
339 : if_else_t<
340 meta::is_trait<_basic_common_reference<T, U>>::value,
341 _basic_common_reference<T, U>,
342 common_type<T, U>>
343 {};
344
345 template<typename T, typename U>
346 struct _common_reference2<T, U, if_t<std::is_reference<_builtin_common_t<T, U>>::value>>
347 : _builtin_common<T, U>
348 {};
349 }
351
354 template<typename ...Ts>
356 {};
357
358 template<typename T>
360 {
361 using type = T;
362 };
363
364 template<typename T, typename U>
365 struct common_reference<T, U>
366 : detail::_common_reference2<T, U>
367 {};
368
369 template<typename... Ts>
370 using common_reference_t = typename common_reference<Ts...>::type;
371
372 template<typename T, typename U, typename... Vs>
373 struct common_reference<T, U, Vs...>
374 : meta::lazy::fold<meta::list<U, Vs...>, T, meta::quote<common_reference_t>>
375 {};
377} // namespace concepts
378
379#endif
typename T::type _t
Type alias for T::type.
Definition meta.hpp:141
typename Fn::template invoke< Args... > invoke
Evaluate the invocable Fn with the arguments Args.
Definition meta.hpp:541
_t< detail::_if_< list< Args... > > > if_
Select one type or another depending on a compile-time Boolean.
Definition meta.hpp:1247
void void_
An alias for void.
Definition meta.hpp:597
Tiny meta-programming library.
Tiny metaprogramming library.
Definition meta.hpp:116
Users can specialize this to hook the common_reference_with concept.
Definition type_traits.hpp:280
Users can specialize this to hook the common_reference_with concept.
Definition type_traits.hpp:356
Users should specialize this to hook the common_with concept until std gets a SFINAE-friendly std::co...
Definition type_traits.hpp:242
Compose the Invocables Fns in the parameter pack Ts.
Definition meta.hpp:881
A wrapper that defers the instantiation of a template C with type parameters Ts in a lambda or let ex...
Definition meta.hpp:787