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 //////////////////////////////////////
71 //////////////////////////////////////
73 //////////////////////////////////////
74 typedef char yes_type;
81 //////////////////////////////////////
83 //////////////////////////////////////
84 template <class T> struct natify{};
86 //////////////////////////////////////
88 //////////////////////////////////////
90 struct remove_reference
96 struct remove_reference<T&>
101 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
104 struct remove_reference<T&&>
112 struct remove_reference< rv<T> >
118 struct remove_reference< rv<T> &>
124 struct remove_reference< const rv<T> &>
131 //////////////////////////////////////
133 //////////////////////////////////////
135 template< class T > struct remove_pointer { typedef T type; };
136 template< class T > struct remove_pointer<T*> { typedef T type; };
137 template< class T > struct remove_pointer<T* const> { typedef T type; };
138 template< class T > struct remove_pointer<T* volatile> { typedef T type; };
139 template< class T > struct remove_pointer<T* const volatile> { typedef T type; };
141 //////////////////////////////////////
143 //////////////////////////////////////
147 typedef typename remove_reference<T>::type* type;
150 //////////////////////////////////////
152 //////////////////////////////////////
156 typedef const T type;
162 typedef const T& type;
165 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
168 struct add_const<T&&>
175 //////////////////////////////////////
176 // add_lvalue_reference
177 //////////////////////////////////////
179 struct add_lvalue_reference
180 { typedef T& type; };
182 template<class T> struct add_lvalue_reference<T&> { typedef T& type; };
183 template<> struct add_lvalue_reference<void> { typedef void type; };
184 template<> struct add_lvalue_reference<const void> { typedef const void type; };
185 template<> struct add_lvalue_reference<volatile void> { typedef volatile void type; };
186 template<> struct add_lvalue_reference<const volatile void>{ typedef const volatile void type; };
189 struct add_const_lvalue_reference
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;
197 //////////////////////////////////////
198 // is_lvalue_reference
199 //////////////////////////////////////
201 struct is_lvalue_reference
203 static const bool value = false;
207 struct is_lvalue_reference<T&>
209 static const bool value = true;
213 //////////////////////////////////////
215 //////////////////////////////////////
220 typedef typename add_const_lvalue_reference<T>::type reference;
221 reference operator()(reference t)
225 //////////////////////////////////////
227 //////////////////////////////////////
229 struct is_class_or_union
231 struct twochar { char dummy[2]; };
233 static char is_class_or_union_tester(void(U::*)(void));
235 static twochar is_class_or_union_tester(...);
236 static const bool value = sizeof(is_class_or_union_tester<T>(0)) == sizeof(char);
239 //////////////////////////////////////
241 //////////////////////////////////////
246 BOOST_MOVE_FORCEINLINE addr_impl_ref( T & v ): v_( v ) {}
247 BOOST_MOVE_FORCEINLINE operator T& () const { return v_; }
250 addr_impl_ref & operator=(const addr_impl_ref &);
254 struct addressof_impl
256 BOOST_MOVE_FORCEINLINE static T * f( T & v, long )
258 return reinterpret_cast<T*>(
259 &const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
262 BOOST_MOVE_FORCEINLINE static T * f( T * v, int )
267 BOOST_MOVE_FORCEINLINE T * addressof( T & v )
269 return ::boost::move_detail::addressof_impl<T>::f
270 ( ::boost::move_detail::addr_impl_ref<T>( v ), 0 );
273 //////////////////////////////////////
275 //////////////////////////////////////
277 struct has_pointer_type
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;
285 //////////////////////////////////////
287 //////////////////////////////////////
288 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
290 //use intrinsic since in MSVC
291 //overaligned types can't go through ellipsis
292 template <class T, class U>
293 struct is_convertible
295 static const bool value = __is_convertible_to(T, U);
300 template <class T, class U>
303 typedef typename add_lvalue_reference<T>::type t_reference;
305 class false_t { char dummy[2]; };
306 static false_t dispatch(...);
307 static true_t dispatch(U);
308 static t_reference trigger();
310 static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t);
315 template <class T, class U, bool IsSame = is_same<T, U>::value>
316 struct is_same_or_convertible
317 : is_convertible<T, U>
320 template <class T, class U>
321 struct is_same_or_convertible<T, U, true>
323 static const bool value = true;
332 : if_c<C,F1,F2>::type
345 #if defined(BOOST_GCC) && (BOOST_GCC <= 40000)
346 #define BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN
349 template<class T, class U, class R = void>
350 struct enable_if_convertible
351 : enable_if< is_convertible<T, U>, R>
354 template<class T, class U, class R = void>
355 struct disable_if_convertible
356 : disable_if< is_convertible<T, U>, R>
359 template<class T, class U, class R = void>
360 struct enable_if_same_or_convertible
361 : enable_if< is_same_or_convertible<T, U>, R>
364 template<class T, class U, class R = void>
365 struct disable_if_same_or_convertible
366 : disable_if< is_same_or_convertible<T, U>, R>
369 //////////////////////////////////////////////////////////////////////////////
373 //////////////////////////////////////////////////////////////////////////////
374 template<bool, class B = true_, class C = true_, class D = true_>
376 : and_impl<B::value, C, D>
380 struct and_impl<true, true_, true_, true_>
382 static const bool value = true;
385 template<class B, class C, class D>
386 struct and_impl<false, B, C, D>
388 static const bool value = false;
391 template<class A, class B, class C = true_, class D = true_>
393 : and_impl<A::value, B, C, D>
396 //////////////////////////////////////////////////////////////////////////////
400 //////////////////////////////////////////////////////////////////////////////
401 template<bool, class B = false_, class C = false_, class D = false_>
403 : or_impl<B::value, C, D>
407 struct or_impl<false, false_, false_, false_>
409 static const bool value = false;
412 template<class B, class C, class D>
413 struct or_impl<true, B, C, D>
415 static const bool value = true;
418 template<class A, class B, class C = false_, class D = false_>
420 : or_impl<A::value, B, C, D>
423 //////////////////////////////////////////////////////////////////////////////
427 //////////////////////////////////////////////////////////////////////////////
431 static const bool value = !T::value;
434 //////////////////////////////////////////////////////////////////////////////
436 // enable_if_and / disable_if_and / enable_if_or / disable_if_or
438 //////////////////////////////////////////////////////////////////////////////
440 template<class R, class A, class B, class C = true_, class D = true_>
442 : enable_if_c< and_<A, B, C, D>::value, R>
445 template<class R, class A, class B, class C = true_, class D = true_>
446 struct disable_if_and
447 : disable_if_c< and_<A, B, C, D>::value, R>
450 template<class R, class A, class B, class C = false_, class D = false_>
452 : enable_if_c< or_<A, B, C, D>::value, R>
455 template<class R, class A, class B, class C = false_, class D = false_>
457 : disable_if_c< or_<A, B, C, D>::value, R>
460 //////////////////////////////////////////////////////////////////////////////
462 // has_move_emulation_enabled_impl
464 //////////////////////////////////////////////////////////////////////////////
466 struct has_move_emulation_enabled_impl
467 : is_convertible< T, ::boost::rv<T>& >
471 struct has_move_emulation_enabled_impl<T&>
472 { static const bool value = false; };
475 struct has_move_emulation_enabled_impl< ::boost::rv<T> >
476 { static const bool value = false; };
478 //////////////////////////////////////////////////////////////////////////////
482 //////////////////////////////////////////////////////////////////////////////
486 { static const bool value = false; };
489 struct is_rv_impl< rv<T> >
490 { static const bool value = true; };
493 struct is_rv_impl< const rv<T> >
494 { static const bool value = true; };
496 // Code from Jeffrey Lee Hellrung, many thanks
499 struct is_rvalue_reference
500 { static const bool value = false; };
502 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
505 struct is_rvalue_reference< T&& >
506 { static const bool value = true; };
508 #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
511 struct is_rvalue_reference< boost::rv<T>& >
512 { static const bool value = true; };
515 struct is_rvalue_reference< const boost::rv<T>& >
516 { static const bool value = true; };
518 #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
520 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
523 struct add_rvalue_reference
524 { typedef T&& type; };
526 #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
528 namespace detail_add_rvalue_reference
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; };
535 template< class T, bool emulation>
536 struct add_rvalue_reference_impl< T, emulation, true > { typedef T & type; };
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
543 struct add_rvalue_reference
544 : detail_add_rvalue_reference::add_rvalue_reference_impl<T>
548 struct add_rvalue_reference<T &>
549 { typedef T & type; };
551 #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
553 template< class T > struct remove_rvalue_reference { typedef T type; };
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
568 // Ideas from Boost.Move review, Jeffrey Lee Hellrung:
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&).
575 //- Add'l TypeTraits has_[trivial_]move_{constructor,assign}...?
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".
580 } //namespace move_detail {
581 } //namespace boost {
583 #include <boost/move/detail/config_end.hpp>
585 #endif //#ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP