1 //////////////////////////////////////////////////////////////////////////////
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)
8 // See http://www.boost.org/libs/move for documentation.
10 //////////////////////////////////////////////////////////////////////////////
14 #ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP
15 #define BOOST_MOVE_DETAIL_META_UTILS_HPP
17 #if defined(BOOST_HAS_PRAGMA_ONCE)
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
25 //Small meta-typetraits to support move
29 //Forward declare boost::rv
30 template <class T> class rv;
32 namespace move_detail {
34 //////////////////////////////////////
36 //////////////////////////////////////
37 template<class T, class U>
40 static const bool value = !is_same<T, U>::value;
43 //////////////////////////////////////
45 //////////////////////////////////////
46 template<class F, class Param>
49 typedef typename F::template apply<Param>::type type;
52 //////////////////////////////////////
54 //////////////////////////////////////
57 struct bool_ : integral_constant<bool, C_>
59 operator bool() const { return C_; }
60 bool operator()() const { return C_; }
63 typedef bool_<true> true_;
64 typedef bool_<false> false_;
66 //////////////////////////////////////
68 //////////////////////////////////////
73 //////////////////////////////////////
75 //////////////////////////////////////
76 typedef char yes_type;
83 //////////////////////////////////////
85 //////////////////////////////////////
86 template <class T> struct natify{};
88 //////////////////////////////////////
90 //////////////////////////////////////
92 struct remove_reference
98 struct remove_reference<T&>
103 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
106 struct remove_reference<T&&>
114 struct remove_reference< rv<T> >
120 struct remove_reference< rv<T> &>
126 struct remove_reference< const rv<T> &>
133 //////////////////////////////////////
135 //////////////////////////////////////
137 template< class T > struct remove_pointer { typedef T type; };
138 template< class T > struct remove_pointer<T*> { typedef T type; };
139 template< class T > struct remove_pointer<T* const> { typedef T type; };
140 template< class T > struct remove_pointer<T* volatile> { typedef T type; };
141 template< class T > struct remove_pointer<T* const volatile> { typedef T type; };
143 //////////////////////////////////////
145 //////////////////////////////////////
149 typedef typename remove_reference<T>::type* type;
152 //////////////////////////////////////
154 //////////////////////////////////////
158 typedef const T type;
164 typedef const T& type;
167 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
170 struct add_const<T&&>
177 //////////////////////////////////////
178 // add_lvalue_reference
179 //////////////////////////////////////
181 struct add_lvalue_reference
182 { typedef T& type; };
184 template<class T> struct add_lvalue_reference<T&> { typedef T& type; };
185 template<> struct add_lvalue_reference<void> { typedef void type; };
186 template<> struct add_lvalue_reference<const void> { typedef const void type; };
187 template<> struct add_lvalue_reference<volatile void> { typedef volatile void type; };
188 template<> struct add_lvalue_reference<const volatile void>{ typedef const volatile void type; };
191 struct add_const_lvalue_reference
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;
199 //////////////////////////////////////
200 // is_lvalue_reference
201 //////////////////////////////////////
203 struct is_lvalue_reference
205 static const bool value = false;
209 struct is_lvalue_reference<T&>
211 static const bool value = true;
215 //////////////////////////////////////
217 //////////////////////////////////////
222 typedef typename add_const_lvalue_reference<T>::type reference;
223 reference operator()(reference t)
227 //////////////////////////////////////
229 //////////////////////////////////////
231 struct is_class_or_union
233 struct twochar { char dummy[2]; };
235 static char is_class_or_union_tester(void(U::*)(void));
237 static twochar is_class_or_union_tester(...);
238 static const bool value = sizeof(is_class_or_union_tester<T>(0)) == sizeof(char);
241 //////////////////////////////////////
243 //////////////////////////////////////
248 BOOST_MOVE_FORCEINLINE addr_impl_ref( T & v ): v_( v ) {}
249 BOOST_MOVE_FORCEINLINE operator T& () const { return v_; }
252 addr_impl_ref & operator=(const addr_impl_ref &);
256 struct addressof_impl
258 BOOST_MOVE_FORCEINLINE static T * f( T & v, long )
260 return reinterpret_cast<T*>(
261 &const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
264 BOOST_MOVE_FORCEINLINE static T * f( T * v, int )
269 BOOST_MOVE_FORCEINLINE T * addressof( T & v )
271 return ::boost::move_detail::addressof_impl<T>::f
272 ( ::boost::move_detail::addr_impl_ref<T>( v ), 0 );
275 //////////////////////////////////////
277 //////////////////////////////////////
279 struct has_pointer_type
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;
287 //////////////////////////////////////
289 //////////////////////////////////////
290 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
292 //use intrinsic since in MSVC
293 //overaligned types can't go through ellipsis
294 template <class T, class U>
295 struct is_convertible
297 static const bool value = __is_convertible_to(T, U);
302 template <class T, class U>
305 typedef typename add_lvalue_reference<T>::type t_reference;
307 class false_t { char dummy[2]; };
308 static false_t dispatch(...);
309 static true_t dispatch(U);
310 static t_reference trigger();
312 static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t);
317 template <class T, class U, bool IsSame = is_same<T, U>::value>
318 struct is_same_or_convertible
319 : is_convertible<T, U>
322 template <class T, class U>
323 struct is_same_or_convertible<T, U, true>
325 static const bool value = true;
334 : if_c<C,F1,F2>::type
347 #if defined(BOOST_GCC) && (BOOST_GCC <= 40000)
348 #define BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN
351 template<class T, class U, class R = void>
352 struct enable_if_convertible
353 : enable_if< is_convertible<T, U>, R>
356 template<class T, class U, class R = void>
357 struct disable_if_convertible
358 : disable_if< is_convertible<T, U>, R>
361 template<class T, class U, class R = void>
362 struct enable_if_same_or_convertible
363 : enable_if< is_same_or_convertible<T, U>, R>
366 template<class T, class U, class R = void>
367 struct disable_if_same_or_convertible
368 : disable_if< is_same_or_convertible<T, U>, R>
371 //////////////////////////////////////////////////////////////////////////////
375 //////////////////////////////////////////////////////////////////////////////
376 template<bool, class B = true_, class C = true_, class D = true_>
378 : and_impl<B::value, C, D>
382 struct and_impl<true, true_, true_, true_>
384 static const bool value = true;
387 template<class B, class C, class D>
388 struct and_impl<false, B, C, D>
390 static const bool value = false;
393 template<class A, class B, class C = true_, class D = true_>
395 : and_impl<A::value, B, C, D>
398 //////////////////////////////////////////////////////////////////////////////
402 //////////////////////////////////////////////////////////////////////////////
403 template<bool, class B = false_, class C = false_, class D = false_>
405 : or_impl<B::value, C, D>
409 struct or_impl<false, false_, false_, false_>
411 static const bool value = false;
414 template<class B, class C, class D>
415 struct or_impl<true, B, C, D>
417 static const bool value = true;
420 template<class A, class B, class C = false_, class D = false_>
422 : or_impl<A::value, B, C, D>
425 //////////////////////////////////////////////////////////////////////////////
429 //////////////////////////////////////////////////////////////////////////////
433 static const bool value = !T::value;
436 //////////////////////////////////////////////////////////////////////////////
438 // enable_if_and / disable_if_and / enable_if_or / disable_if_or
440 //////////////////////////////////////////////////////////////////////////////
442 template<class R, class A, class B, class C = true_, class D = true_>
444 : enable_if_c< and_<A, B, C, D>::value, R>
447 template<class R, class A, class B, class C = true_, class D = true_>
448 struct disable_if_and
449 : disable_if_c< and_<A, B, C, D>::value, R>
452 template<class R, class A, class B, class C = false_, class D = false_>
454 : enable_if_c< or_<A, B, C, D>::value, R>
457 template<class R, class A, class B, class C = false_, class D = false_>
459 : disable_if_c< or_<A, B, C, D>::value, R>
462 //////////////////////////////////////////////////////////////////////////////
464 // has_move_emulation_enabled_impl
466 //////////////////////////////////////////////////////////////////////////////
468 struct has_move_emulation_enabled_impl
469 : is_convertible< T, ::boost::rv<T>& >
473 struct has_move_emulation_enabled_impl<T&>
474 { static const bool value = false; };
477 struct has_move_emulation_enabled_impl< ::boost::rv<T> >
478 { static const bool value = false; };
480 //////////////////////////////////////////////////////////////////////////////
484 //////////////////////////////////////////////////////////////////////////////
488 { static const bool value = false; };
491 struct is_rv_impl< rv<T> >
492 { static const bool value = true; };
495 struct is_rv_impl< const rv<T> >
496 { static const bool value = true; };
498 // Code from Jeffrey Lee Hellrung, many thanks
501 struct is_rvalue_reference
502 { static const bool value = false; };
504 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
507 struct is_rvalue_reference< T&& >
508 { static const bool value = true; };
510 #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
513 struct is_rvalue_reference< boost::rv<T>& >
514 { static const bool value = true; };
517 struct is_rvalue_reference< const boost::rv<T>& >
518 { static const bool value = true; };
520 #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
522 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
525 struct add_rvalue_reference
526 { typedef T&& type; };
528 #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
530 namespace detail_add_rvalue_reference
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; };
537 template< class T, bool emulation>
538 struct add_rvalue_reference_impl< T, emulation, true > { typedef T & type; };
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
545 struct add_rvalue_reference
546 : detail_add_rvalue_reference::add_rvalue_reference_impl<T>
550 struct add_rvalue_reference<T &>
551 { typedef T & type; };
553 #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
555 template< class T > struct remove_rvalue_reference { typedef T type; };
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
570 // Ideas from Boost.Move review, Jeffrey Lee Hellrung:
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&).
577 //- Add'l TypeTraits has_[trivial_]move_{constructor,assign}...?
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".
582 } //namespace move_detail {
583 } //namespace boost {
585 #include <boost/move/detail/config_end.hpp>
587 #endif //#ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP