EVOLUTION-MANAGER
Edit File: meta_utils.hpp
////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2012-2015. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/move for documentation. // ////////////////////////////////////////////////////////////////////////////// //! \file #ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP #define BOOST_MOVE_DETAIL_META_UTILS_HPP #if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif #include <boost/move/detail/config_begin.hpp> #include <boost/move/detail/workaround.hpp> //forceinline #include <boost/move/detail/meta_utils_core.hpp> #include <cstddef> //for std::size_t //Small meta-typetraits to support move namespace boost { //Forward declare boost::rv template <class T> class rv; namespace move_detail { ////////////////////////////////////// // is_different ////////////////////////////////////// template<class T, class U> struct is_different { static const bool value = !is_same<T, U>::value; }; ////////////////////////////////////// // apply ////////////////////////////////////// template<class F, class Param> struct apply { typedef typename F::template apply<Param>::type type; }; ////////////////////////////////////// // bool_ ////////////////////////////////////// template< bool C_ > struct bool_ : integral_constant<bool, C_> { operator bool() const { return C_; } bool operator()() const { return C_; } }; typedef bool_<true> true_; typedef bool_<false> false_; ////////////////////////////////////// // nat ////////////////////////////////////// struct nat{}; struct nat2{}; struct nat3{}; ////////////////////////////////////// // yes_type/no_type ////////////////////////////////////// typedef char yes_type; struct no_type { char _[2]; }; ////////////////////////////////////// // natify ////////////////////////////////////// template <class T> struct natify{}; ////////////////////////////////////// // remove_reference ////////////////////////////////////// template<class T> struct remove_reference { typedef T type; }; template<class T> struct remove_reference<T&> { typedef T type; }; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template<class T> struct remove_reference<T&&> { typedef T type; }; #else template<class T> struct remove_reference< rv<T> > { typedef T type; }; template<class T> struct remove_reference< rv<T> &> { typedef T type; }; template<class T> struct remove_reference< const rv<T> &> { typedef T type; }; #endif ////////////////////////////////////// // remove_pointer ////////////////////////////////////// template< class T > struct remove_pointer { typedef T type; }; template< class T > struct remove_pointer<T*> { typedef T type; }; template< class T > struct remove_pointer<T* const> { typedef T type; }; template< class T > struct remove_pointer<T* volatile> { typedef T type; }; template< class T > struct remove_pointer<T* const volatile> { typedef T type; }; ////////////////////////////////////// // add_pointer ////////////////////////////////////// template< class T > struct add_pointer { typedef typename remove_reference<T>::type* type; }; ////////////////////////////////////// // add_const ////////////////////////////////////// template<class T> struct add_const { typedef const T type; }; template<class T> struct add_const<T&> { typedef const T& type; }; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template<class T> struct add_const<T&&> { typedef T&& type; }; #endif ////////////////////////////////////// // add_lvalue_reference ////////////////////////////////////// template<class T> struct add_lvalue_reference { typedef T& type; }; template<class T> struct add_lvalue_reference<T&> { typedef T& type; }; template<> struct add_lvalue_reference<void> { typedef void type; }; template<> struct add_lvalue_reference<const void> { typedef const void type; }; template<> struct add_lvalue_reference<volatile void> { typedef volatile void type; }; template<> struct add_lvalue_reference<const volatile void>{ typedef const volatile void type; }; template<class T> struct add_const_lvalue_reference { typedef typename remove_reference<T>::type t_unreferenced; typedef typename add_const<t_unreferenced>::type t_unreferenced_const; typedef typename add_lvalue_reference <t_unreferenced_const>::type type; }; ////////////////////////////////////// // is_lvalue_reference ////////////////////////////////////// template<class T> struct is_lvalue_reference { static const bool value = false; }; template<class T> struct is_lvalue_reference<T&> { static const bool value = true; }; ////////////////////////////////////// // identity ////////////////////////////////////// template <class T> struct identity { typedef T type; typedef typename add_const_lvalue_reference<T>::type reference; reference operator()(reference t) { return t; } }; ////////////////////////////////////// // is_class_or_union ////////////////////////////////////// template<class T> struct is_class_or_union { struct twochar { char dummy[2]; }; template <class U> static char is_class_or_union_tester(void(U::*)(void)); template <class U> static twochar is_class_or_union_tester(...); static const bool value = sizeof(is_class_or_union_tester<T>(0)) == sizeof(char); }; ////////////////////////////////////// // addressof ////////////////////////////////////// template<class T> struct addr_impl_ref { T & v_; BOOST_MOVE_FORCEINLINE addr_impl_ref( T & v ): v_( v ) {} BOOST_MOVE_FORCEINLINE operator T& () const { return v_; } private: addr_impl_ref & operator=(const addr_impl_ref &); }; template<class T> struct addressof_impl { BOOST_MOVE_FORCEINLINE static T * f( T & v, long ) { return reinterpret_cast<T*>( &const_cast<char&>(reinterpret_cast<const volatile char &>(v))); } BOOST_MOVE_FORCEINLINE static T * f( T * v, int ) { return v; } }; template<class T> BOOST_MOVE_FORCEINLINE T * addressof( T & v ) { return ::boost::move_detail::addressof_impl<T>::f ( ::boost::move_detail::addr_impl_ref<T>( v ), 0 ); } ////////////////////////////////////// // has_pointer_type ////////////////////////////////////// template <class T> struct has_pointer_type { struct two { char c[2]; }; template <class U> static two test(...); template <class U> static char test(typename U::pointer* = 0); static const bool value = sizeof(test<T>(0)) == 1; }; ////////////////////////////////////// // is_convertible ////////////////////////////////////// #if defined(_MSC_VER) && (_MSC_VER >= 1400) //use intrinsic since in MSVC //overaligned types can't go through ellipsis template <class T, class U> struct is_convertible { static const bool value = __is_convertible_to(T, U); }; #else template <class T, class U> class is_convertible { typedef typename add_lvalue_reference<T>::type t_reference; typedef char true_t; class false_t { char dummy[2]; }; static false_t dispatch(...); static true_t dispatch(U); static t_reference trigger(); public: static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t); }; #endif template <class T, class U, bool IsSame = is_same<T, U>::value> struct is_same_or_convertible : is_convertible<T, U> {}; template <class T, class U> struct is_same_or_convertible<T, U, true> { static const bool value = true; }; template< bool C , typename F1 , typename F2 > struct eval_if_c : if_c<C,F1,F2>::type {}; template< typename C , typename T1 , typename T2 > struct eval_if : if_<C,T1,T2>::type {}; #if defined(BOOST_GCC) && (BOOST_GCC <= 40000) #define BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN #endif template<class T, class U, class R = void> struct enable_if_convertible : enable_if< is_convertible<T, U>, R> {}; template<class T, class U, class R = void> struct disable_if_convertible : disable_if< is_convertible<T, U>, R> {}; template<class T, class U, class R = void> struct enable_if_same_or_convertible : enable_if< is_same_or_convertible<T, U>, R> {}; template<class T, class U, class R = void> struct disable_if_same_or_convertible : disable_if< is_same_or_convertible<T, U>, R> {}; ////////////////////////////////////////////////////////////////////////////// // // and_ // ////////////////////////////////////////////////////////////////////////////// template<bool, class B = true_, class C = true_, class D = true_> struct and_impl : and_impl<B::value, C, D> {}; template<> struct and_impl<true, true_, true_, true_> { static const bool value = true; }; template<class B, class C, class D> struct and_impl<false, B, C, D> { static const bool value = false; }; template<class A, class B, class C = true_, class D = true_> struct and_ : and_impl<A::value, B, C, D> {}; ////////////////////////////////////////////////////////////////////////////// // // or_ // ////////////////////////////////////////////////////////////////////////////// template<bool, class B = false_, class C = false_, class D = false_> struct or_impl : or_impl<B::value, C, D> {}; template<> struct or_impl<false, false_, false_, false_> { static const bool value = false; }; template<class B, class C, class D> struct or_impl<true, B, C, D> { static const bool value = true; }; template<class A, class B, class C = false_, class D = false_> struct or_ : or_impl<A::value, B, C, D> {}; ////////////////////////////////////////////////////////////////////////////// // // not_ // ////////////////////////////////////////////////////////////////////////////// template<class T> struct not_ { static const bool value = !T::value; }; ////////////////////////////////////////////////////////////////////////////// // // enable_if_and / disable_if_and / enable_if_or / disable_if_or // ////////////////////////////////////////////////////////////////////////////// template<class R, class A, class B, class C = true_, class D = true_> struct enable_if_and : enable_if_c< and_<A, B, C, D>::value, R> {}; template<class R, class A, class B, class C = true_, class D = true_> struct disable_if_and : disable_if_c< and_<A, B, C, D>::value, R> {}; template<class R, class A, class B, class C = false_, class D = false_> struct enable_if_or : enable_if_c< or_<A, B, C, D>::value, R> {}; template<class R, class A, class B, class C = false_, class D = false_> struct disable_if_or : disable_if_c< or_<A, B, C, D>::value, R> {}; ////////////////////////////////////////////////////////////////////////////// // // has_move_emulation_enabled_impl // ////////////////////////////////////////////////////////////////////////////// template<class T> struct has_move_emulation_enabled_impl : is_convertible< T, ::boost::rv<T>& > {}; template<class T> struct has_move_emulation_enabled_impl<T&> { static const bool value = false; }; template<class T> struct has_move_emulation_enabled_impl< ::boost::rv<T> > { static const bool value = false; }; ////////////////////////////////////////////////////////////////////////////// // // is_rv_impl // ////////////////////////////////////////////////////////////////////////////// template <class T> struct is_rv_impl { static const bool value = false; }; template <class T> struct is_rv_impl< rv<T> > { static const bool value = true; }; template <class T> struct is_rv_impl< const rv<T> > { static const bool value = true; }; // Code from Jeffrey Lee Hellrung, many thanks template< class T > struct is_rvalue_reference { static const bool value = false; }; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template< class T > struct is_rvalue_reference< T&& > { static const bool value = true; }; #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template< class T > struct is_rvalue_reference< boost::rv<T>& > { static const bool value = true; }; template< class T > struct is_rvalue_reference< const boost::rv<T>& > { static const bool value = true; }; #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template< class T > struct add_rvalue_reference { typedef T&& type; }; #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES namespace detail_add_rvalue_reference { template< class T , bool emulation = has_move_emulation_enabled_impl<T>::value , bool rv = is_rv_impl<T>::value > struct add_rvalue_reference_impl { typedef T type; }; template< class T, bool emulation> struct add_rvalue_reference_impl< T, emulation, true > { typedef T & type; }; template< class T, bool rv > struct add_rvalue_reference_impl< T, true, rv > { typedef ::boost::rv<T>& type; }; } // namespace detail_add_rvalue_reference template< class T > struct add_rvalue_reference : detail_add_rvalue_reference::add_rvalue_reference_impl<T> { }; template< class T > struct add_rvalue_reference<T &> { typedef T & type; }; #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template< class T > struct remove_rvalue_reference { typedef T type; }; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template< class T > struct remove_rvalue_reference< T&& > { typedef T type; }; #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template< class T > struct remove_rvalue_reference< rv<T> > { typedef T type; }; template< class T > struct remove_rvalue_reference< const rv<T> > { typedef T type; }; template< class T > struct remove_rvalue_reference< volatile rv<T> > { typedef T type; }; template< class T > struct remove_rvalue_reference< const volatile rv<T> > { typedef T type; }; template< class T > struct remove_rvalue_reference< rv<T>& > { typedef T type; }; template< class T > struct remove_rvalue_reference< const rv<T>& > { typedef T type; }; template< class T > struct remove_rvalue_reference< volatile rv<T>& > { typedef T type; }; template< class T > struct remove_rvalue_reference< const volatile rv<T>& >{ typedef T type; }; #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES // Ideas from Boost.Move review, Jeffrey Lee Hellrung: // //- TypeTraits metafunctions is_lvalue_reference, add_lvalue_reference, and remove_lvalue_reference ? // Perhaps add_reference and remove_reference can be modified so that they behave wrt emulated rvalue // references the same as wrt real rvalue references, i.e., add_reference< rv<T>& > -> T& rather than // rv<T>& (since T&& & -> T&). // //- Add'l TypeTraits has_[trivial_]move_{constructor,assign}...? // //- An as_lvalue(T& x) function, which amounts to an identity operation in C++0x, but strips emulated // rvalue references in C++03. This may be necessary to prevent "accidental moves". } //namespace move_detail { } //namespace boost { #include <boost/move/detail/config_end.hpp> #endif //#ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP