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