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#ifndef BOOST_CONFIG_HPP
18# include <boost/config.hpp>
19#endif
20#
21#if defined(BOOST_HAS_PRAGMA_ONCE)
22# pragma once
23#endif
24#include <boost/move/detail/meta_utils_core.hpp>
25#include <cstddef> //for std::size_t
26
27//Small meta-typetraits to support move
28
29namespace boost {
30
31//Forward declare boost::rv
32template <class T> class rv;
33
34namespace move_detail {
35
36//////////////////////////////////////
37// is_different
38//////////////////////////////////////
39template<class T, class U>
40struct is_different
41{
42 static const bool value = !is_same<T, U>::value;
43};
44
45//////////////////////////////////////
46// apply
47//////////////////////////////////////
48template<class F, class Param>
49struct apply
50{
51 typedef typename F::template apply<Param>::type type;
52};
53
54//////////////////////////////////////
55// bool_
56//////////////////////////////////////
57
58template< bool C_ >
59struct bool_ : integral_constant<bool, C_>
60{
61 operator bool() const { return C_; }
62 bool operator()() const { return C_; }
63};
64
65typedef bool_<true> true_;
66typedef bool_<false> false_;
67
68//////////////////////////////////////
69// nat
70//////////////////////////////////////
71struct nat{};
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 inline addr_impl_ref( T & v ): v_( v ) {}
249 inline 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 static inline T * f( T & v, long )
259 {
260 return reinterpret_cast<T*>(
261 &const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
262 }
263
264 static inline T * f( T * v, int )
265 { return v; }
266};
267
268template<class T>
269inline 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<
318 bool C
319 , typename F1
320 , typename F2
321 >
322struct eval_if_c
323 : if_c<C,F1,F2>::type
324{};
325
326template<
327 typename C
328 , typename T1
329 , typename T2
330 >
331struct eval_if
332 : if_<C,T1,T2>::type
333{};
334
335
336#if defined(BOOST_GCC) && (BOOST_GCC <= 40000)
337#define BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN
338#endif
339
340template<class T, class U, class R = void>
341struct enable_if_convertible
342 : enable_if< is_convertible<T, U>, R>
343{};
344
345template<class T, class U, class R = void>
346struct disable_if_convertible
347 : disable_if< is_convertible<T, U>, R>
348{};
349
350//////////////////////////////////////////////////////////////////////////////
351//
352// and_
353//
354//////////////////////////////////////////////////////////////////////////////
355template<bool, class B = true_, class C = true_, class D = true_>
356struct and_impl
357 : and_impl<B::value, C, D>
358{};
359
360template<>
361struct and_impl<true, true_, true_, true_>
362{
363 static const bool value = true;
364};
365
366template<class B, class C, class D>
367struct and_impl<false, B, C, D>
368{
369 static const bool value = false;
370};
371
372template<class A, class B, class C = true_, class D = true_>
373struct and_
374 : and_impl<A::value, B, C, D>
375{};
376
377//////////////////////////////////////////////////////////////////////////////
378//
379// or_
380//
381//////////////////////////////////////////////////////////////////////////////
382template<bool, class B = false_, class C = false_, class D = false_>
383struct or_impl
384 : or_impl<B::value, C, D>
385{};
386
387template<>
388struct or_impl<false, false_, false_, false_>
389{
390 static const bool value = false;
391};
392
393template<class B, class C, class D>
394struct or_impl<true, B, C, D>
395{
396 static const bool value = true;
397};
398
399template<class A, class B, class C = false_, class D = false_>
400struct or_
401 : or_impl<A::value, B, C, D>
402{};
403
404//////////////////////////////////////////////////////////////////////////////
405//
406// not_
407//
408//////////////////////////////////////////////////////////////////////////////
409template<class T>
410struct not_
411{
412 static const bool value = !T::value;
413};
414
415//////////////////////////////////////////////////////////////////////////////
416//
417// enable_if_and / disable_if_and / enable_if_or / disable_if_or
418//
419//////////////////////////////////////////////////////////////////////////////
420
421template<class R, class A, class B, class C = true_, class D = true_>
422struct enable_if_and
423 : enable_if_c< and_<A, B, C, D>::value, R>
424{};
425
426template<class R, class A, class B, class C = true_, class D = true_>
427struct disable_if_and
428 : disable_if_c< and_<A, B, C, D>::value, R>
429{};
430
431template<class R, class A, class B, class C = false_, class D = false_>
432struct enable_if_or
433 : enable_if_c< or_<A, B, C, D>::value, R>
434{};
435
436template<class R, class A, class B, class C = false_, class D = false_>
437struct disable_if_or
438 : disable_if_c< or_<A, B, C, D>::value, R>
439{};
440
441//////////////////////////////////////////////////////////////////////////////
442//
443// has_move_emulation_enabled_impl
444//
445//////////////////////////////////////////////////////////////////////////////
446template<class T>
447struct has_move_emulation_enabled_impl
448 : is_convertible< T, ::boost::rv<T>& >
449{};
450
451template<class T>
452struct has_move_emulation_enabled_impl<T&>
453{ static const bool value = false; };
454
455template<class T>
456struct has_move_emulation_enabled_impl< ::boost::rv<T> >
457{ static const bool value = false; };
458
459//////////////////////////////////////////////////////////////////////////////
460//
461// is_rv_impl
462//
463//////////////////////////////////////////////////////////////////////////////
464
465template <class T>
466struct is_rv_impl
467{ static const bool value = false; };
468
469template <class T>
470struct is_rv_impl< rv<T> >
471{ static const bool value = true; };
472
473template <class T>
474struct is_rv_impl< const rv<T> >
475{ static const bool value = true; };
476
477// Code from Jeffrey Lee Hellrung, many thanks
478
479template< class T >
480struct is_rvalue_reference
481{ static const bool value = false; };
482
483#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
484
485template< class T >
486struct is_rvalue_reference< T&& >
487{ static const bool value = true; };
488
489#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
490
491template< class T >
492struct is_rvalue_reference< boost::rv<T>& >
493{ static const bool value = true; };
494
495template< class T >
496struct is_rvalue_reference< const boost::rv<T>& >
497{ static const bool value = true; };
498
499#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
500
501#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
502
503template< class T >
504struct add_rvalue_reference
505{ typedef T&& type; };
506
507#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
508
509namespace detail_add_rvalue_reference
510{
511 template< class T
512 , bool emulation = has_move_emulation_enabled_impl<T>::value
513 , bool rv = is_rv_impl<T>::value >
514 struct add_rvalue_reference_impl { typedef T type; };
515
516 template< class T, bool emulation>
517 struct add_rvalue_reference_impl< T, emulation, true > { typedef T & type; };
518
519 template< class T, bool rv >
520 struct add_rvalue_reference_impl< T, true, rv > { typedef ::boost::rv<T>& type; };
521} // namespace detail_add_rvalue_reference
522
523template< class T >
524struct add_rvalue_reference
525 : detail_add_rvalue_reference::add_rvalue_reference_impl<T>
526{ };
527
528template< class T >
529struct add_rvalue_reference<T &>
530{ typedef T & type; };
531
532#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
533
534template< class T > struct remove_rvalue_reference { typedef T type; };
535
536#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
537 template< class T > struct remove_rvalue_reference< T&& > { typedef T type; };
538#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
539 template< class T > struct remove_rvalue_reference< rv<T> > { typedef T type; };
540 template< class T > struct remove_rvalue_reference< const rv<T> > { typedef T type; };
541 template< class T > struct remove_rvalue_reference< volatile rv<T> > { typedef T type; };
542 template< class T > struct remove_rvalue_reference< const volatile rv<T> > { typedef T type; };
543 template< class T > struct remove_rvalue_reference< rv<T>& > { typedef T type; };
544 template< class T > struct remove_rvalue_reference< const rv<T>& > { typedef T type; };
545 template< class T > struct remove_rvalue_reference< volatile rv<T>& > { typedef T type; };
546 template< class T > struct remove_rvalue_reference< const volatile rv<T>& >{ typedef T type; };
547#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
548
549// Ideas from Boost.Move review, Jeffrey Lee Hellrung:
550//
551//- TypeTraits metafunctions is_lvalue_reference, add_lvalue_reference, and remove_lvalue_reference ?
552// Perhaps add_reference and remove_reference can be modified so that they behave wrt emulated rvalue
553// references the same as wrt real rvalue references, i.e., add_reference< rv<T>& > -> T& rather than
554// rv<T>& (since T&& & -> T&).
555//
556//- Add'l TypeTraits has_[trivial_]move_{constructor,assign}...?
557//
558//- An as_lvalue(T& x) function, which amounts to an identity operation in C++0x, but strips emulated
559// rvalue references in C++03. This may be necessary to prevent "accidental moves".
560
561} //namespace move_detail {
562} //namespace boost {
563
564#endif //#ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP
565