1//////////////////////////////////////////////////////////////////////////////
2//
3// (C) Copyright Ion Gaztanaga 2012-2015.
4// Distributed under the Boost Software License, Version 1.0.
5// (See accompanying file LICENSE_1_0.txt or copy at
6// http://www.boost.org/LICENSE_1_0.txt)
7//
8// See http://www.boost.org/libs/move for documentation.
9//
10//////////////////////////////////////////////////////////////////////////////
11
12//! \file
13
14#ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP
15#define BOOST_MOVE_DETAIL_META_UTILS_HPP
16
17#if defined(BOOST_HAS_PRAGMA_ONCE)
18# pragma once
19#endif
20#include <boost/move/detail/config_begin.hpp>
21#include <boost/move/detail/workaround.hpp> //forceinline
22#include <boost/move/detail/meta_utils_core.hpp>
23#include <cstddef> //for std::size_t
24#include <boost/move/detail/addressof.hpp>
25
26//Small meta-typetraits to support move
27
28namespace boost {
29
30//Forward declare boost::rv
31template <class T> class rv;
32
33namespace move_detail {
34
35//////////////////////////////////////
36// is_different
37//////////////////////////////////////
38template<class T, class U>
39struct is_different
40{
41 static const bool value = !is_same<T, U>::value;
42};
43
44//////////////////////////////////////
45// apply
46//////////////////////////////////////
47template<class F, class Param>
48struct apply
49{
50 typedef typename F::template apply<Param>::type type;
51};
52
53//////////////////////////////////////
54// bool_
55//////////////////////////////////////
56
57template< bool C_ >
58struct bool_ : integral_constant<bool, C_>
59{
60 BOOST_MOVE_FORCEINLINE operator bool() const { return C_; }
61 BOOST_MOVE_FORCEINLINE bool operator()() const { return C_; }
62};
63
64typedef bool_<true> true_;
65typedef bool_<false> false_;
66
67//////////////////////////////////////
68// nat
69//////////////////////////////////////
70struct nat{};
71struct nat2{};
72struct nat3{};
73
74template <unsigned N>
75struct natN
76{};
77
78//////////////////////////////////////
79// yes_type/no_type
80//////////////////////////////////////
81typedef char yes_type;
82
83struct no_type
84{
85 char _[2];
86};
87
88//////////////////////////////////////
89// natify
90//////////////////////////////////////
91template <class T> struct natify{};
92
93//////////////////////////////////////
94// remove_reference
95//////////////////////////////////////
96template<class T>
97struct remove_reference
98{
99 typedef T type;
100};
101
102template<class T>
103struct remove_reference<T&>
104{
105 typedef T type;
106};
107
108#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
109
110template<class T>
111struct remove_reference<T&&>
112{
113 typedef T type;
114};
115
116#else
117
118template<class T>
119struct remove_reference< rv<T> >
120{
121 typedef T type;
122};
123
124template<class T>
125struct remove_reference< rv<T> &>
126{
127 typedef T type;
128};
129
130template<class T>
131struct remove_reference< const rv<T> &>
132{
133 typedef T type;
134};
135
136#endif
137
138//////////////////////////////////////
139// remove_pointer
140//////////////////////////////////////
141
142template< class T > struct remove_pointer { typedef T type; };
143template< class T > struct remove_pointer<T*> { typedef T type; };
144template< class T > struct remove_pointer<T* const> { typedef T type; };
145template< class T > struct remove_pointer<T* volatile> { typedef T type; };
146template< class T > struct remove_pointer<T* const volatile> { typedef T type; };
147
148//////////////////////////////////////
149// add_pointer
150//////////////////////////////////////
151template< class T >
152struct add_pointer
153{
154 typedef typename remove_reference<T>::type* type;
155};
156
157//////////////////////////////////////
158// add_const
159//////////////////////////////////////
160template<class T>
161struct add_const
162{
163 typedef const T type;
164};
165
166template<class T>
167struct add_const<T&>
168{
169 typedef const T& type;
170};
171
172#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
173
174template<class T>
175struct add_const<T&&>
176{
177 typedef T&& type;
178};
179
180#endif
181
182//////////////////////////////////////
183// add_lvalue_reference
184//////////////////////////////////////
185template<class T>
186struct add_lvalue_reference
187{ typedef T& type; };
188
189template<class T> struct add_lvalue_reference<T&> { typedef T& type; };
190template<> struct add_lvalue_reference<void> { typedef void type; };
191template<> struct add_lvalue_reference<const void> { typedef const void type; };
192template<> struct add_lvalue_reference<volatile void> { typedef volatile void type; };
193template<> struct add_lvalue_reference<const volatile void>{ typedef const volatile void type; };
194
195template<class T>
196struct add_const_lvalue_reference
197{
198 typedef typename remove_reference<T>::type t_unreferenced;
199 typedef typename add_const<t_unreferenced>::type t_unreferenced_const;
200 typedef typename add_lvalue_reference
201 <t_unreferenced_const>::type type;
202};
203
204//////////////////////////////////////
205// is_lvalue_reference
206//////////////////////////////////////
207template<class T>
208struct is_lvalue_reference
209{
210 static const bool value = false;
211};
212
213template<class T>
214struct is_lvalue_reference<T&>
215{
216 static const bool value = true;
217};
218
219
220//////////////////////////////////////
221// identity
222//////////////////////////////////////
223template <class T>
224struct identity
225{
226 typedef T type;
227 typedef typename add_const_lvalue_reference<T>::type reference;
228 BOOST_MOVE_FORCEINLINE reference operator()(reference t) const
229 { return t; }
230};
231
232//////////////////////////////////////
233// is_class_or_union
234//////////////////////////////////////
235template<class T>
236struct is_class_or_union
237{
238 struct twochar { char dummy[2]; };
239 template <class U>
240 static char is_class_or_union_tester(void(U::*)(void));
241 template <class U>
242 static twochar is_class_or_union_tester(...);
243 static const bool value = sizeof(is_class_or_union_tester<T>(0)) == sizeof(char);
244};
245
246//////////////////////////////////////
247// addressof
248//////////////////////////////////////
249
250
251//////////////////////////////////////
252// has_pointer_type
253//////////////////////////////////////
254template <class T>
255struct has_pointer_type
256{
257 struct two { char c[2]; };
258 template <class U> static two test(...);
259 template <class U> static char test(typename U::pointer* = 0);
260 static const bool value = sizeof(test<T>(0)) == 1;
261};
262
263//////////////////////////////////////
264// is_convertible
265//////////////////////////////////////
266#if defined(_MSC_VER) && (_MSC_VER >= 1400)
267
268//use intrinsic since in MSVC
269//overaligned types can't go through ellipsis
270template <class T, class U>
271struct is_convertible
272{
273 static const bool value = __is_convertible_to(T, U);
274};
275
276#else
277
278template <class T, class U>
279class is_convertible
280{
281 typedef typename add_lvalue_reference<T>::type t_reference;
282 typedef char true_t;
283 class false_t { char dummy[2]; };
284 static false_t dispatch(...);
285 static true_t dispatch(U);
286 static t_reference trigger();
287 public:
288 static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t);
289};
290
291#endif
292
293template <class T, class U, bool IsSame = is_same<T, U>::value>
294struct is_same_or_convertible
295 : is_convertible<T, U>
296{};
297
298template <class T, class U>
299struct is_same_or_convertible<T, U, true>
300{
301 static const bool value = true;
302};
303
304template<
305 bool C
306 , typename F1
307 , typename F2
308 >
309struct eval_if_c
310 : if_c<C,F1,F2>::type
311{};
312
313template<
314 typename C
315 , typename T1
316 , typename T2
317 >
318struct eval_if
319 : if_<C,T1,T2>::type
320{};
321
322
323#if defined(BOOST_GCC) && (BOOST_GCC <= 40000)
324#define BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN
325#endif
326
327template<class T, class U, class R = void>
328struct enable_if_convertible
329 : enable_if< is_convertible<T, U>, R>
330{};
331
332template<class T, class U, class R = void>
333struct disable_if_convertible
334 : disable_if< is_convertible<T, U>, R>
335{};
336
337template<class T, class U, class R = void>
338struct enable_if_same_or_convertible
339 : enable_if< is_same_or_convertible<T, U>, R>
340{};
341
342template<class T, class U, class R = void>
343struct disable_if_same_or_convertible
344 : disable_if< is_same_or_convertible<T, U>, R>
345{};
346
347//////////////////////////////////////////////////////////////////////////////
348//
349// and_
350//
351//////////////////////////////////////////////////////////////////////////////
352template<bool, class B = true_, class C = true_, class D = true_>
353struct and_impl
354 : and_impl<B::value, C, D>
355{};
356
357template<>
358struct and_impl<true, true_, true_, true_>
359{
360 static const bool value = true;
361};
362
363template<class B, class C, class D>
364struct and_impl<false, B, C, D>
365{
366 static const bool value = false;
367};
368
369template<class A, class B, class C = true_, class D = true_>
370struct and_
371 : and_impl<A::value, B, C, D>
372{};
373
374//////////////////////////////////////////////////////////////////////////////
375//
376// or_
377//
378//////////////////////////////////////////////////////////////////////////////
379template<bool, class B = false_, class C = false_, class D = false_>
380struct or_impl
381 : or_impl<B::value, C, D>
382{};
383
384template<>
385struct or_impl<false, false_, false_, false_>
386{
387 static const bool value = false;
388};
389
390template<class B, class C, class D>
391struct or_impl<true, B, C, D>
392{
393 static const bool value = true;
394};
395
396template<class A, class B, class C = false_, class D = false_>
397struct or_
398 : or_impl<A::value, B, C, D>
399{};
400
401//////////////////////////////////////////////////////////////////////////////
402//
403// not_
404//
405//////////////////////////////////////////////////////////////////////////////
406template<class T>
407struct not_
408{
409 static const bool value = !T::value;
410};
411
412//////////////////////////////////////////////////////////////////////////////
413//
414// enable_if_and / disable_if_and / enable_if_or / disable_if_or
415//
416//////////////////////////////////////////////////////////////////////////////
417
418template<class R, class A, class B, class C = true_, class D = true_>
419struct enable_if_and
420 : enable_if_c< and_<A, B, C, D>::value, R>
421{};
422
423template<class R, class A, class B, class C = true_, class D = true_>
424struct disable_if_and
425 : disable_if_c< and_<A, B, C, D>::value, R>
426{};
427
428template<class R, class A, class B, class C = false_, class D = false_>
429struct enable_if_or
430 : enable_if_c< or_<A, B, C, D>::value, R>
431{};
432
433template<class R, class A, class B, class C = false_, class D = false_>
434struct disable_if_or
435 : disable_if_c< or_<A, B, C, D>::value, R>
436{};
437
438//////////////////////////////////////////////////////////////////////////////
439//
440// has_move_emulation_enabled_impl
441//
442//////////////////////////////////////////////////////////////////////////////
443template<class T>
444struct has_move_emulation_enabled_impl
445 : is_convertible< T, ::boost::rv<T>& >
446{};
447
448template<class T>
449struct has_move_emulation_enabled_impl<T&>
450{ static const bool value = false; };
451
452template<class T>
453struct has_move_emulation_enabled_impl< ::boost::rv<T> >
454{ static const bool value = false; };
455
456//////////////////////////////////////////////////////////////////////////////
457//
458// is_rv_impl
459//
460//////////////////////////////////////////////////////////////////////////////
461
462template <class T>
463struct is_rv_impl
464{ static const bool value = false; };
465
466template <class T>
467struct is_rv_impl< rv<T> >
468{ static const bool value = true; };
469
470template <class T>
471struct is_rv_impl< const rv<T> >
472{ static const bool value = true; };
473
474// Code from Jeffrey Lee Hellrung, many thanks
475
476template< class T >
477struct is_rvalue_reference
478{ static const bool value = false; };
479
480#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
481
482template< class T >
483struct is_rvalue_reference< T&& >
484{ static const bool value = true; };
485
486#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
487
488template< class T >
489struct is_rvalue_reference< boost::rv<T>& >
490{ static const bool value = true; };
491
492template< class T >
493struct is_rvalue_reference< const boost::rv<T>& >
494{ static const bool value = true; };
495
496#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
497
498#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
499
500template< class T >
501struct add_rvalue_reference
502{ typedef T&& type; };
503
504#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
505
506namespace detail_add_rvalue_reference
507{
508 template< class T
509 , bool emulation = has_move_emulation_enabled_impl<T>::value
510 , bool rv = is_rv_impl<T>::value >
511 struct add_rvalue_reference_impl { typedef T type; };
512
513 template< class T, bool emulation>
514 struct add_rvalue_reference_impl< T, emulation, true > { typedef T & type; };
515
516 template< class T, bool rv >
517 struct add_rvalue_reference_impl< T, true, rv > { typedef ::boost::rv<T>& type; };
518} // namespace detail_add_rvalue_reference
519
520template< class T >
521struct add_rvalue_reference
522 : detail_add_rvalue_reference::add_rvalue_reference_impl<T>
523{ };
524
525template< class T >
526struct add_rvalue_reference<T &>
527{ typedef T & type; };
528
529#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
530
531template< class T > struct remove_rvalue_reference { typedef T type; };
532
533#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
534 template< class T > struct remove_rvalue_reference< T&& > { typedef T type; };
535#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
536 template< class T > struct remove_rvalue_reference< rv<T> > { typedef T type; };
537 template< class T > struct remove_rvalue_reference< const rv<T> > { typedef T type; };
538 template< class T > struct remove_rvalue_reference< volatile rv<T> > { typedef T type; };
539 template< class T > struct remove_rvalue_reference< const volatile rv<T> > { typedef T type; };
540 template< class T > struct remove_rvalue_reference< rv<T>& > { typedef T type; };
541 template< class T > struct remove_rvalue_reference< const rv<T>& > { typedef T type; };
542 template< class T > struct remove_rvalue_reference< volatile rv<T>& > { typedef T type; };
543 template< class T > struct remove_rvalue_reference< const volatile rv<T>& >{ typedef T type; };
544#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
545
546// Ideas from Boost.Move review, Jeffrey Lee Hellrung:
547//
548//- TypeTraits metafunctions is_lvalue_reference, add_lvalue_reference, and remove_lvalue_reference ?
549// Perhaps add_reference and remove_reference can be modified so that they behave wrt emulated rvalue
550// references the same as wrt real rvalue references, i.e., add_reference< rv<T>& > -> T& rather than
551// rv<T>& (since T&& & -> T&).
552//
553//- Add'l TypeTraits has_[trivial_]move_{constructor,assign}...?
554//
555//- An as_lvalue(T& x) function, which amounts to an identity operation in C++0x, but strips emulated
556// rvalue references in C++03. This may be necessary to prevent "accidental moves".
557
558} //namespace move_detail {
559} //namespace boost {
560
561#include <boost/move/detail/config_end.hpp>
562
563#endif //#ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP
564