Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@101: // (C) Copyright Ion Gaztanaga 2012-2015. Chris@16: // Distributed under the Boost Software License, Version 1.0. Chris@16: // (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // See http://www.boost.org/libs/move for documentation. Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: //! \file Chris@16: Chris@16: #ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP Chris@16: #define BOOST_MOVE_DETAIL_META_UTILS_HPP Chris@16: Chris@101: #ifndef BOOST_CONFIG_HPP Chris@101: # include Chris@101: #endif Chris@101: # Chris@101: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@101: # pragma once Chris@101: #endif Chris@101: #include Chris@101: #include //for std::size_t Chris@16: Chris@16: //Small meta-typetraits to support move Chris@16: Chris@16: namespace boost { Chris@101: Chris@101: //Forward declare boost::rv Chris@101: template class rv; Chris@101: Chris@16: namespace move_detail { Chris@16: Chris@101: ////////////////////////////////////// Chris@101: // nat Chris@101: ////////////////////////////////////// Chris@101: struct nat{}; Chris@16: Chris@101: ////////////////////////////////////// Chris@101: // natify Chris@101: ////////////////////////////////////// Chris@101: template struct natify{}; Chris@16: Chris@101: ////////////////////////////////////// Chris@101: // remove_reference Chris@101: ////////////////////////////////////// Chris@101: template Chris@101: struct remove_reference Chris@16: { Chris@16: typedef T type; Chris@16: }; Chris@16: Chris@101: template Chris@101: struct remove_reference Chris@16: { Chris@16: typedef T type; Chris@16: }; Chris@16: Chris@101: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: Chris@101: template Chris@101: struct remove_reference Chris@16: { Chris@101: typedef T type; Chris@16: }; Chris@16: Chris@101: #else Chris@16: Chris@101: template Chris@101: struct remove_reference< rv > Chris@101: { Chris@101: typedef T type; Chris@101: }; Chris@16: Chris@101: template Chris@101: struct remove_reference< rv &> Chris@101: { Chris@101: typedef T type; Chris@101: }; Chris@101: Chris@101: template Chris@101: struct remove_reference< const rv &> Chris@101: { Chris@101: typedef T type; Chris@101: }; Chris@101: Chris@101: Chris@101: #endif Chris@101: Chris@101: ////////////////////////////////////// Chris@101: // add_const Chris@101: ////////////////////////////////////// Chris@101: template Chris@101: struct add_const Chris@101: { Chris@101: typedef const T type; Chris@101: }; Chris@101: Chris@101: template Chris@101: struct add_const Chris@101: { Chris@101: typedef const T& type; Chris@101: }; Chris@101: Chris@101: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: Chris@101: template Chris@101: struct add_const Chris@101: { Chris@101: typedef T&& type; Chris@101: }; Chris@101: Chris@101: #endif Chris@101: Chris@101: ////////////////////////////////////// Chris@101: // add_lvalue_reference Chris@101: ////////////////////////////////////// Chris@101: template Chris@101: struct add_lvalue_reference Chris@101: { typedef T& type; }; Chris@101: Chris@101: template struct add_lvalue_reference { typedef T& type; }; Chris@101: template<> struct add_lvalue_reference { typedef void type; }; Chris@101: template<> struct add_lvalue_reference { typedef const void type; }; Chris@101: template<> struct add_lvalue_reference { typedef volatile void type; }; Chris@101: template<> struct add_lvalue_reference{ typedef const volatile void type; }; Chris@101: Chris@101: template Chris@101: struct add_const_lvalue_reference Chris@101: { Chris@101: typedef typename remove_reference::type t_unreferenced; Chris@101: typedef typename add_const::type t_unreferenced_const; Chris@101: typedef typename add_lvalue_reference Chris@101: ::type type; Chris@101: }; Chris@101: Chris@101: ////////////////////////////////////// Chris@101: // is_lvalue_reference Chris@101: ////////////////////////////////////// Chris@16: template Chris@16: struct is_lvalue_reference Chris@101: { Chris@101: static const bool value = false; Chris@101: }; Chris@16: Chris@16: template Chris@16: struct is_lvalue_reference Chris@101: { Chris@101: static const bool value = true; Chris@101: }; Chris@16: Chris@101: ////////////////////////////////////// Chris@101: // is_class_or_union Chris@101: ////////////////////////////////////// Chris@16: template Chris@16: struct is_class_or_union Chris@16: { Chris@101: struct twochar { char dummy[2]; }; Chris@16: template Chris@16: static char is_class_or_union_tester(void(U::*)(void)); Chris@16: template Chris@16: static twochar is_class_or_union_tester(...); Chris@16: static const bool value = sizeof(is_class_or_union_tester(0)) == sizeof(char); Chris@16: }; Chris@16: Chris@101: ////////////////////////////////////// Chris@101: // addressof Chris@101: ////////////////////////////////////// Chris@101: template Chris@101: struct addr_impl_ref Chris@16: { Chris@16: T & v_; Chris@16: inline addr_impl_ref( T & v ): v_( v ) {} Chris@16: inline operator T& () const { return v_; } Chris@16: Chris@16: private: Chris@16: addr_impl_ref & operator=(const addr_impl_ref &); Chris@16: }; Chris@16: Chris@101: template Chris@101: struct addressof_impl Chris@16: { Chris@16: static inline T * f( T & v, long ) Chris@16: { Chris@16: return reinterpret_cast( Chris@16: &const_cast(reinterpret_cast(v))); Chris@16: } Chris@16: Chris@16: static inline T * f( T * v, int ) Chris@16: { return v; } Chris@16: }; Chris@16: Chris@16: template Chris@16: inline T * addressof( T & v ) Chris@16: { Chris@16: return ::boost::move_detail::addressof_impl::f Chris@16: ( ::boost::move_detail::addr_impl_ref( v ), 0 ); Chris@16: } Chris@16: Chris@101: ////////////////////////////////////// Chris@101: // has_pointer_type Chris@101: ////////////////////////////////////// Chris@101: template Chris@101: struct has_pointer_type Chris@101: { Chris@101: struct two { char c[2]; }; Chris@101: template static two test(...); Chris@101: template static char test(typename U::pointer* = 0); Chris@101: static const bool value = sizeof(test(0)) == 1; Chris@101: }; Chris@101: Chris@101: ////////////////////////////////////// Chris@101: // is_convertible Chris@101: ////////////////////////////////////// Chris@101: #if defined(_MSC_VER) && (_MSC_VER >= 1400) Chris@101: Chris@101: //use intrinsic since in MSVC Chris@101: //overaligned types can't go through ellipsis Chris@101: template Chris@101: struct is_convertible Chris@101: { Chris@101: static const bool value = __is_convertible_to(T, U); Chris@101: }; Chris@101: Chris@101: #else Chris@101: Chris@101: template Chris@101: class is_convertible Chris@101: { Chris@101: typedef typename add_lvalue_reference::type t_reference; Chris@101: typedef char true_t; Chris@101: class false_t { char dummy[2]; }; Chris@101: static false_t dispatch(...); Chris@101: static true_t dispatch(U); Chris@101: static t_reference trigger(); Chris@101: public: Chris@101: static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t); Chris@101: }; Chris@101: Chris@101: #endif Chris@101: Chris@101: ////////////////////////////////////////////////////////////////////////////// Chris@101: // Chris@101: // has_move_emulation_enabled_impl Chris@101: // Chris@101: ////////////////////////////////////////////////////////////////////////////// Chris@101: template Chris@101: struct has_move_emulation_enabled_impl Chris@101: : is_convertible< T, ::boost::rv& > Chris@101: {}; Chris@101: Chris@101: template Chris@101: struct has_move_emulation_enabled_impl Chris@101: { static const bool value = false; }; Chris@101: Chris@101: template Chris@101: struct has_move_emulation_enabled_impl< ::boost::rv > Chris@101: { static const bool value = false; }; Chris@101: Chris@101: ////////////////////////////////////////////////////////////////////////////// Chris@101: // Chris@101: // is_rv_impl Chris@101: // Chris@101: ////////////////////////////////////////////////////////////////////////////// Chris@101: Chris@101: template Chris@101: struct is_rv_impl Chris@101: { static const bool value = false; }; Chris@101: Chris@101: template Chris@101: struct is_rv_impl< rv > Chris@101: { static const bool value = true; }; Chris@101: Chris@101: template Chris@101: struct is_rv_impl< const rv > Chris@101: { static const bool value = true; }; Chris@101: Chris@101: // Code from Jeffrey Lee Hellrung, many thanks Chris@101: Chris@101: template< class T > Chris@101: struct is_rvalue_reference Chris@101: { static const bool value = false; }; Chris@101: Chris@101: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: Chris@101: template< class T > Chris@101: struct is_rvalue_reference< T&& > Chris@101: { static const bool value = true; }; Chris@101: Chris@101: #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: Chris@101: template< class T > Chris@101: struct is_rvalue_reference< boost::rv& > Chris@101: { static const bool value = true; }; Chris@101: Chris@101: template< class T > Chris@101: struct is_rvalue_reference< const boost::rv& > Chris@101: { static const bool value = true; }; Chris@101: Chris@101: #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: Chris@101: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: Chris@101: template< class T > Chris@101: struct add_rvalue_reference Chris@101: { typedef T&& type; }; Chris@101: Chris@101: #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: Chris@101: namespace detail_add_rvalue_reference Chris@101: { Chris@101: template< class T Chris@101: , bool emulation = has_move_emulation_enabled_impl::value Chris@101: , bool rv = is_rv_impl::value > Chris@101: struct add_rvalue_reference_impl { typedef T type; }; Chris@101: Chris@101: template< class T, bool emulation> Chris@101: struct add_rvalue_reference_impl< T, emulation, true > { typedef T & type; }; Chris@101: Chris@101: template< class T, bool rv > Chris@101: struct add_rvalue_reference_impl< T, true, rv > { typedef ::boost::rv& type; }; Chris@101: } // namespace detail_add_rvalue_reference Chris@101: Chris@101: template< class T > Chris@101: struct add_rvalue_reference Chris@101: : detail_add_rvalue_reference::add_rvalue_reference_impl Chris@101: { }; Chris@101: Chris@101: template< class T > Chris@101: struct add_rvalue_reference Chris@101: { typedef T & type; }; Chris@101: Chris@101: #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: Chris@101: template< class T > struct remove_rvalue_reference { typedef T type; }; Chris@101: Chris@101: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: template< class T > struct remove_rvalue_reference< T&& > { typedef T type; }; Chris@101: #else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: template< class T > struct remove_rvalue_reference< rv > { typedef T type; }; Chris@101: template< class T > struct remove_rvalue_reference< const rv > { typedef T type; }; Chris@101: template< class T > struct remove_rvalue_reference< volatile rv > { typedef T type; }; Chris@101: template< class T > struct remove_rvalue_reference< const volatile rv > { typedef T type; }; Chris@101: template< class T > struct remove_rvalue_reference< rv& > { typedef T type; }; Chris@101: template< class T > struct remove_rvalue_reference< const rv& > { typedef T type; }; Chris@101: template< class T > struct remove_rvalue_reference< volatile rv& > { typedef T type; }; Chris@101: template< class T > struct remove_rvalue_reference< const volatile rv& >{ typedef T type; }; Chris@101: #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@101: Chris@101: // Ideas from Boost.Move review, Jeffrey Lee Hellrung: Chris@101: // Chris@101: //- TypeTraits metafunctions is_lvalue_reference, add_lvalue_reference, and remove_lvalue_reference ? Chris@101: // Perhaps add_reference and remove_reference can be modified so that they behave wrt emulated rvalue Chris@101: // references the same as wrt real rvalue references, i.e., add_reference< rv& > -> T& rather than Chris@101: // rv& (since T&& & -> T&). Chris@101: // Chris@101: //- Add'l TypeTraits has_[trivial_]move_{constructor,assign}...? Chris@101: // Chris@101: //- An as_lvalue(T& x) function, which amounts to an identity operation in C++0x, but strips emulated Chris@101: // rvalue references in C++03. This may be necessary to prevent "accidental moves". Chris@101: Chris@16: } //namespace move_detail { Chris@16: } //namespace boost { Chris@16: Chris@16: #endif //#ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP