Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // (C) Copyright Ion Gaztanaga 2012-2012. Chris@102: // Distributed under the Boost Software License, Version 1.0. Chris@102: // (See accompanying file LICENSE_1_0.txt or copy at Chris@102: // http://www.boost.org/LICENSE_1_0.txt) Chris@102: // Chris@102: // See http://www.boost.org/libs/move for documentation. Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: //! \file Chris@102: //! This header defines core utilities to ease the development Chris@102: //! of move-aware functions. This header minimizes dependencies Chris@102: //! from other libraries. Chris@102: Chris@102: #ifndef BOOST_MOVE_MOVE_UTILITY_CORE_HPP Chris@102: #define BOOST_MOVE_MOVE_UTILITY_CORE_HPP Chris@102: Chris@102: #ifndef BOOST_CONFIG_HPP Chris@102: # include Chris@102: #endif Chris@102: # Chris@102: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@102: # pragma once Chris@102: #endif Chris@102: Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: Chris@102: #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED) Chris@102: Chris@102: namespace boost { Chris@102: Chris@102: template Chris@102: struct enable_move_utility_emulation Chris@102: { Chris@102: static const bool value = true; Chris@102: }; Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // move() Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: template Chris@102: inline typename ::boost::move_detail::enable_if_c Chris@102: < enable_move_utility_emulation::value && !has_move_emulation_enabled::value, T&>::type Chris@102: move(T& x) BOOST_NOEXCEPT Chris@102: { Chris@102: return x; Chris@102: } Chris@102: Chris@102: template Chris@102: inline typename ::boost::move_detail::enable_if_c Chris@102: < enable_move_utility_emulation::value && has_move_emulation_enabled::value, rv&>::type Chris@102: move(T& x) BOOST_NOEXCEPT Chris@102: { Chris@102: return *static_cast* >(::boost::move_detail::addressof(x)); Chris@102: } Chris@102: Chris@102: template Chris@102: inline typename ::boost::move_detail::enable_if_c Chris@102: < enable_move_utility_emulation::value && has_move_emulation_enabled::value, rv&>::type Chris@102: move(rv& x) BOOST_NOEXCEPT Chris@102: { Chris@102: return x; Chris@102: } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // forward() Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: template Chris@102: inline typename ::boost::move_detail::enable_if_c Chris@102: < enable_move_utility_emulation::value && ::boost::move_detail::is_rv::value, T &>::type Chris@102: forward(const typename ::boost::move_detail::identity::type &x) BOOST_NOEXCEPT Chris@102: { Chris@102: return const_cast(x); Chris@102: } Chris@102: Chris@102: template Chris@102: inline typename ::boost::move_detail::enable_if_c Chris@102: < enable_move_utility_emulation::value && !::boost::move_detail::is_rv::value, const T &>::type Chris@102: forward(const typename ::boost::move_detail::identity::type &x) BOOST_NOEXCEPT Chris@102: { Chris@102: return x; Chris@102: } Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // move_if_not_lvalue_reference() Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: template Chris@102: inline typename ::boost::move_detail::enable_if_c Chris@102: < enable_move_utility_emulation::value && Chris@102: ::boost::move_detail::is_rv::value Chris@102: , T &>::type Chris@102: move_if_not_lvalue_reference(const typename ::boost::move_detail::identity::type &x) BOOST_NOEXCEPT Chris@102: { Chris@102: return const_cast(x); Chris@102: } Chris@102: Chris@102: template Chris@102: inline typename ::boost::move_detail::enable_if_c Chris@102: < enable_move_utility_emulation::value && Chris@102: !::boost::move_detail::is_rv::value && Chris@102: (::boost::move_detail::is_lvalue_reference::value || Chris@102: !has_move_emulation_enabled::value) Chris@102: , typename ::boost::move_detail::add_lvalue_reference::type Chris@102: >::type Chris@102: move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference::type &x) BOOST_NOEXCEPT Chris@102: { Chris@102: return x; Chris@102: } Chris@102: Chris@102: template Chris@102: inline typename ::boost::move_detail::enable_if_c Chris@102: < enable_move_utility_emulation::value && Chris@102: !::boost::move_detail::is_rv::value && Chris@102: (!::boost::move_detail::is_lvalue_reference::value && Chris@102: has_move_emulation_enabled::value) Chris@102: , rv& Chris@102: >::type Chris@102: move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference::type &x) BOOST_NOEXCEPT Chris@102: { Chris@102: return move(x); Chris@102: } Chris@102: Chris@102: } //namespace boost Chris@102: Chris@102: #else //#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED) Chris@102: Chris@102: #if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE) Chris@102: #include Chris@102: Chris@102: namespace boost{ Chris@102: Chris@102: using ::std::move; Chris@102: using ::std::forward; Chris@102: Chris@102: } //namespace boost Chris@102: Chris@102: #else //!BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE Chris@102: Chris@102: namespace boost { Chris@102: Chris@102: //! This trait's internal boolean `value` is false in compilers with rvalue references Chris@102: //! and true in compilers without rvalue references. Chris@102: //! Chris@102: //! A user can specialize this trait for a type T to false to SFINAE out `move` and `forward` Chris@102: //! so that the user can define a different move emulation for that type in namespace boost Chris@102: //! (e.g. another Boost library for its types) and avoid any overload ambiguity. Chris@102: template Chris@102: struct enable_move_utility_emulation Chris@102: { Chris@102: static const bool value = false; Chris@102: }; Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // move Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: #if defined(BOOST_MOVE_DOXYGEN_INVOKED) Chris@102: //! This function provides a way to convert a reference into a rvalue reference Chris@102: //! in compilers with rvalue references. For other compilers if `T` is Boost.Move Chris@102: //! enabled type then it converts `T&` into ::boost::rv & so that Chris@102: //! move emulation is activated, else it returns `T &`. Chris@102: template Chris@102: rvalue_reference move(input_reference) noexcept; Chris@102: Chris@102: #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) Chris@102: Chris@102: //Old move approach, lvalues could bind to rvalue references Chris@102: template Chris@102: inline typename ::boost::move_detail::remove_reference::type && move(T&& t) BOOST_NOEXCEPT Chris@102: { return t; } Chris@102: Chris@102: #else //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES Chris@102: Chris@102: template Chris@102: inline typename ::boost::move_detail::remove_reference::type && move(T&& t) BOOST_NOEXCEPT Chris@102: { return static_cast::type &&>(t); } Chris@102: Chris@102: #endif //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // forward Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: Chris@102: #if defined(BOOST_MOVE_DOXYGEN_INVOKED) Chris@102: //! This function provides limited form of forwarding that is usually enough for Chris@102: //! in-place construction and avoids the exponential overloading for Chris@102: //! achieve the limited forwarding in C++03. Chris@102: //! Chris@102: //! For compilers with rvalue references this function provides perfect forwarding. Chris@102: //! Chris@102: //! Otherwise: Chris@102: //! * If input_reference binds to const ::boost::rv & then it output_reference is Chris@102: //! ::boost::rv & Chris@102: //! Chris@102: //! * Else, output_reference is equal to input_reference. Chris@102: template output_reference forward(input_reference) noexcept; Chris@102: #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) Chris@102: Chris@102: //Old move approach, lvalues could bind to rvalue references Chris@102: Chris@102: template Chris@102: inline T&& forward(typename ::boost::move_detail::identity::type&& t) BOOST_NOEXCEPT Chris@102: { return t; } Chris@102: Chris@102: #else //Old move Chris@102: Chris@102: template Chris@102: inline T&& forward(typename ::boost::move_detail::remove_reference::type& t) BOOST_NOEXCEPT Chris@102: { return static_cast(t); } Chris@102: Chris@102: template Chris@102: inline T&& forward(typename ::boost::move_detail::remove_reference::type&& t) BOOST_NOEXCEPT Chris@102: { Chris@102: //"boost::forward error: 'T' is a lvalue reference, can't forward as rvalue."; Chris@102: BOOST_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference::value); Chris@102: return static_cast(t); Chris@102: } Chris@102: Chris@102: #endif //BOOST_MOVE_DOXYGEN_INVOKED Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // move_if_not_lvalue_reference Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: Chris@102: Chris@102: #if defined(BOOST_MOVE_DOXYGEN_INVOKED) Chris@102: template output_reference move_if_not_lvalue_reference(input_reference) noexcept; Chris@102: #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) Chris@102: Chris@102: //Old move approach, lvalues could bind to rvalue references Chris@102: Chris@102: template Chris@102: inline T&& move_if_not_lvalue_reference(typename ::boost::move_detail::identity::type&& t) BOOST_NOEXCEPT Chris@102: { return t; } Chris@102: Chris@102: #else //Old move Chris@102: Chris@102: template Chris@102: inline T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference::type& t) BOOST_NOEXCEPT Chris@102: { return static_cast(t); } Chris@102: Chris@102: template Chris@102: inline T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference::type&& t) BOOST_NOEXCEPT Chris@102: { Chris@102: //"boost::forward error: 'T' is a lvalue reference, can't forward as rvalue."; Chris@102: BOOST_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference::value); Chris@102: return static_cast(t); Chris@102: } Chris@102: Chris@102: #endif //BOOST_MOVE_DOXYGEN_INVOKED Chris@102: Chris@102: } //namespace boost { Chris@102: Chris@102: #endif //#if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE) Chris@102: Chris@102: #endif //BOOST_NO_CXX11_RVALUE_REFERENCES Chris@102: Chris@102: #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) Chris@102: Chris@102: namespace boost{ Chris@102: namespace move_detail{ Chris@102: Chris@102: template Chris@102: typename boost::move_detail::add_rvalue_reference::type declval(); Chris@102: Chris@102: } //namespace move_detail{ Chris@102: } //namespace boost{ Chris@102: Chris@102: #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED) Chris@102: Chris@102: Chris@102: #include Chris@102: Chris@102: #endif //#ifndef BOOST_MOVE_MOVE_UTILITY_CORE_HPP