Horizon
type_traits.hpp
Go to the documentation of this file.
1 // 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 
21 namespace 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>
241  struct common_type
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>
280  {};
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>,
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
CPP_concept type
\concept type
Definition: concepts.hpp:838
template(typename ActionFn, typename Rng)(concept(invocable_action_closure_)(ActionFn
\concept invocable_action_closure_
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