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

source code of include/boost/move/detail/meta_utils.hpp