Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // (C) Copyright Ion Gaztanaga 2012-2012. 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@101: //! \file Chris@16: //! This header implements macros to define movable classes and Chris@16: //! move-aware functions Chris@16: Chris@16: #ifndef BOOST_MOVE_CORE_HPP Chris@16: #define BOOST_MOVE_CORE_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: Chris@16: #include Chris@101: #include Chris@16: Chris@16: //boost_move_no_copy_constructor_or_assign typedef Chris@16: //used to detect noncopyable types for other Boost libraries. Chris@101: #if defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@16: #define BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE) \ Chris@16: private:\ Chris@16: TYPE(TYPE &);\ Chris@16: TYPE& operator=(TYPE &);\ Chris@16: public:\ Chris@16: typedef int boost_move_no_copy_constructor_or_assign; \ Chris@16: private:\ Chris@16: // Chris@16: #else Chris@16: #define BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE) \ Chris@16: public:\ Chris@16: TYPE(TYPE const &) = delete;\ Chris@16: TYPE& operator=(TYPE const &) = delete;\ Chris@16: public:\ Chris@16: typedef int boost_move_no_copy_constructor_or_assign; \ Chris@16: private:\ Chris@16: // Chris@16: #endif //BOOST_NO_CXX11_DELETED_FUNCTIONS Chris@16: Chris@16: #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED) Chris@16: Chris@101: #include Chris@16: Chris@16: //Move emulation rv breaks standard aliasing rules so add workarounds for some compilers Chris@101: #if defined(__GNUC__) && (__GNUC__ >= 4) && \ Chris@101: (\ Chris@101: defined(BOOST_GCC) || \ Chris@101: (defined(BOOST_INTEL) && (BOOST_INTEL_CXX_VERSION >= 1300)) \ Chris@101: ) Chris@16: #define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS __attribute__((__may_alias__)) Chris@16: #else Chris@16: #define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS Chris@16: #endif Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // struct rv Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: class rv Chris@16: : public ::boost::move_detail::if_c Chris@101: < ::boost::move_detail::is_class::value Chris@16: , T Chris@101: , ::boost::move_detail::nat Chris@16: >::type Chris@16: { Chris@16: rv(); Chris@101: ~rv() throw(); Chris@16: rv(rv const&); Chris@16: void operator=(rv const&); Chris@16: } BOOST_MOVE_ATTRIBUTE_MAY_ALIAS; Chris@16: Chris@16: Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@101: // is_rv Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: namespace move_detail { Chris@16: Chris@16: template Chris@16: struct is_rv Chris@101: //Derive from integral constant because some Boost code assummes it has Chris@101: //a "type" internal typedef Chris@101: : integral_constant::value > Chris@16: {}; Chris@16: Chris@16: } //namespace move_detail { Chris@16: Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // has_move_emulation_enabled Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct has_move_emulation_enabled Chris@101: : ::boost::move_detail::has_move_emulation_enabled_impl Chris@16: {}; Chris@16: Chris@16: } //namespace boost { Chris@16: Chris@16: #define BOOST_RV_REF(TYPE)\ Chris@16: ::boost::rv< TYPE >& \ Chris@16: // Chris@16: Chris@16: #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ Chris@16: ::boost::rv< TYPE >& \ Chris@16: // Chris@16: Chris@16: #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ Chris@16: ::boost::rv< TYPE >& \ Chris@16: // Chris@16: Chris@16: #define BOOST_RV_REF_BEG\ Chris@16: ::boost::rv< \ Chris@16: // Chris@16: Chris@16: #define BOOST_RV_REF_END\ Chris@16: >& \ Chris@16: // Chris@16: Chris@16: #define BOOST_FWD_REF(TYPE)\ Chris@16: const TYPE & \ Chris@16: // Chris@16: Chris@16: #define BOOST_COPY_ASSIGN_REF(TYPE)\ Chris@16: const ::boost::rv< TYPE >& \ Chris@16: // Chris@16: Chris@16: #define BOOST_COPY_ASSIGN_REF_BEG \ Chris@16: const ::boost::rv< \ Chris@16: // Chris@16: Chris@16: #define BOOST_COPY_ASSIGN_REF_END \ Chris@16: >& \ Chris@16: // Chris@16: Chris@16: #define BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ Chris@16: const ::boost::rv< TYPE >& \ Chris@16: // Chris@16: Chris@16: #define BOOST_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ Chris@16: const ::boost::rv< TYPE >& \ Chris@16: // Chris@16: Chris@16: #define BOOST_CATCH_CONST_RLVALUE(TYPE)\ Chris@16: const ::boost::rv< TYPE >& \ Chris@16: // Chris@16: Chris@101: namespace boost { Chris@101: namespace move_detail { Chris@101: Chris@101: template Chris@101: inline typename ::boost::move_detail::enable_if_c Chris@101: < ::boost::move_detail::is_lvalue_reference::value || Chris@101: !::boost::has_move_emulation_enabled::value Chris@101: , T&>::type Chris@101: move_return(T& x) BOOST_NOEXCEPT Chris@101: { Chris@101: return x; Chris@101: } Chris@101: Chris@101: template Chris@101: inline typename ::boost::move_detail::enable_if_c Chris@101: < !::boost::move_detail::is_lvalue_reference::value && Chris@101: ::boost::has_move_emulation_enabled::value Chris@101: , ::boost::rv&>::type Chris@101: move_return(T& x) BOOST_NOEXCEPT Chris@101: { Chris@101: return *static_cast< ::boost::rv* >(::boost::move_detail::addressof(x)); Chris@101: } Chris@101: Chris@101: template Chris@101: inline typename ::boost::move_detail::enable_if_c Chris@101: < !::boost::move_detail::is_lvalue_reference::value && Chris@101: ::boost::has_move_emulation_enabled::value Chris@101: , ::boost::rv&>::type Chris@101: move_return(::boost::rv& x) BOOST_NOEXCEPT Chris@101: { Chris@101: return x; Chris@101: } Chris@101: Chris@101: } //namespace move_detail { Chris@101: } //namespace boost { Chris@101: Chris@101: #define BOOST_MOVE_RET(RET_TYPE, REF)\ Chris@101: boost::move_detail::move_return< RET_TYPE >(REF) Chris@101: // Chris@101: Chris@101: #define BOOST_MOVE_BASE(BASE_TYPE, ARG) \ Chris@101: ::boost::move((BASE_TYPE&)(ARG)) Chris@101: // Chris@101: Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // BOOST_MOVABLE_BUT_NOT_COPYABLE Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\ Chris@16: BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\ Chris@16: public:\ Chris@16: operator ::boost::rv&() \ Chris@16: { return *static_cast< ::boost::rv* >(this); }\ Chris@16: operator const ::boost::rv&() const \ Chris@16: { return *static_cast* >(this); }\ Chris@16: private:\ Chris@16: // Chris@16: Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // BOOST_COPYABLE_AND_MOVABLE Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\ Chris@16: public:\ Chris@16: TYPE& operator=(TYPE &t)\ Chris@16: { this->operator=(static_cast &>(const_cast(t))); return *this;}\ Chris@16: public:\ Chris@16: operator ::boost::rv&() \ Chris@16: { return *static_cast< ::boost::rv* >(this); }\ Chris@16: operator const ::boost::rv&() const \ Chris@16: { return *static_cast* >(this); }\ Chris@16: private:\ Chris@16: // Chris@16: Chris@16: #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\ Chris@16: public:\ Chris@16: operator ::boost::rv&() \ Chris@16: { return *static_cast< ::boost::rv* >(this); }\ Chris@16: operator const ::boost::rv&() const \ Chris@16: { return *static_cast* >(this); }\ Chris@16: private:\ Chris@16: // Chris@16: Chris@101: namespace boost{ Chris@101: namespace move_detail{ Chris@101: Chris@101: template< class T> Chris@101: struct forward_type Chris@101: { typedef const T &type; }; Chris@101: Chris@101: template< class T> Chris@101: struct forward_type< boost::rv > Chris@101: { typedef T type; }; Chris@101: Chris@101: }} Chris@101: Chris@16: #else //BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: Chris@16: //! This macro marks a type as movable but not copyable, disabling copy construction Chris@16: //! and assignment. The user will need to write a move constructor/assignment as explained Chris@16: //! in the documentation to fully write a movable but not copyable class. Chris@16: #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\ Chris@16: BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\ Chris@16: public:\ Chris@16: typedef int boost_move_emulation_t;\ Chris@16: // Chris@16: Chris@16: //! This macro marks a type as copyable and movable. Chris@16: //! The user will need to write a move constructor/assignment and a copy assignment Chris@16: //! as explained in the documentation to fully write a copyable and movable class. Chris@16: #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\ Chris@16: // Chris@16: Chris@16: #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) Chris@16: #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\ Chris@16: // Chris@16: #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED) Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: //!This trait yields to a compile-time true boolean if T was marked as Chris@16: //!BOOST_MOVABLE_BUT_NOT_COPYABLE or BOOST_COPYABLE_AND_MOVABLE and Chris@16: //!rvalue references are not available on the platform. False otherwise. Chris@16: template Chris@16: struct has_move_emulation_enabled Chris@16: { Chris@16: static const bool value = false; Chris@16: }; Chris@16: Chris@16: } //namespace boost{ Chris@16: Chris@16: //!This macro is used to achieve portable syntax in move Chris@16: //!constructors and assignments for classes marked as Chris@16: //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE Chris@16: #define BOOST_RV_REF(TYPE)\ Chris@16: TYPE && \ Chris@16: // Chris@16: Chris@16: //!This macro is used to achieve portable syntax in move Chris@16: //!constructors and assignments for template classes marked as Chris@16: //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE. Chris@101: //!As macros have problems with comma-separated template arguments, Chris@101: //!the template argument must be preceded with BOOST_RV_REF_BEG Chris@16: //!and ended with BOOST_RV_REF_END Chris@16: #define BOOST_RV_REF_BEG\ Chris@16: \ Chris@16: // Chris@16: Chris@16: //!This macro is used to achieve portable syntax in move Chris@16: //!constructors and assignments for template classes marked as Chris@16: //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE. Chris@101: //!As macros have problems with comma-separated template arguments, Chris@101: //!the template argument must be preceded with BOOST_RV_REF_BEG Chris@16: //!and ended with BOOST_RV_REF_END Chris@16: #define BOOST_RV_REF_END\ Chris@16: && \ Chris@16: Chris@16: //!This macro is used to achieve portable syntax in copy Chris@16: //!assignment for classes marked as BOOST_COPYABLE_AND_MOVABLE. Chris@16: #define BOOST_COPY_ASSIGN_REF(TYPE)\ Chris@16: const TYPE & \ Chris@16: // Chris@16: Chris@16: //! This macro is used to implement portable perfect forwarding Chris@16: //! as explained in the documentation. Chris@16: #define BOOST_FWD_REF(TYPE)\ Chris@16: TYPE && \ Chris@16: // Chris@16: Chris@16: #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) Chris@16: Chris@16: #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ Chris@16: TYPE && \ Chris@16: // Chris@16: Chris@16: #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ Chris@16: TYPE && \ Chris@16: // Chris@16: Chris@16: #define BOOST_COPY_ASSIGN_REF_BEG \ Chris@16: const \ Chris@16: // Chris@16: Chris@16: #define BOOST_COPY_ASSIGN_REF_END \ Chris@16: & \ Chris@16: // Chris@16: Chris@16: #define BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ Chris@16: const TYPE & \ Chris@16: // Chris@16: Chris@16: #define BOOST_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ Chris@16: const TYPE& \ Chris@16: // Chris@16: Chris@16: #define BOOST_CATCH_CONST_RLVALUE(TYPE)\ Chris@16: const TYPE & \ Chris@16: // Chris@16: Chris@101: #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED) Chris@16: Chris@101: #if !defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED) Chris@101: Chris@101: //!This macro is used to achieve portable move return semantics. Chris@101: //!The C++11 Standard allows implicit move returns when the object to be returned Chris@101: //!is designated by a lvalue and: Chris@101: //! - The criteria for elision of a copy operation are met OR Chris@101: //! - The criteria would be met save for the fact that the source object is a function parameter Chris@101: //! Chris@101: //!For C++11 conforming compilers this macros only yields to REF: Chris@101: //! return BOOST_MOVE_RET(RET_TYPE, REF); -> return REF; Chris@101: //! Chris@101: //!For compilers without rvalue references Chris@101: //!this macro does an explicit move if the move emulation is activated Chris@101: //!and the return type (RET_TYPE) is not a reference. Chris@101: //! Chris@101: //!For non-conforming compilers with rvalue references like Visual 2010 & 2012, Chris@101: //!an explicit move is performed if RET_TYPE is not a reference. Chris@101: //! Chris@101: //! Caution: When using this macro in non-conforming or C++03 Chris@101: //!compilers, a move will be performed even if the C++11 standard does not allow it Chris@101: //!(e.g. returning a static variable). The user is responsible for using this macro Chris@101: //!only to return local objects that met C++11 criteria. Chris@101: #define BOOST_MOVE_RET(RET_TYPE, REF)\ Chris@101: REF Chris@101: // Chris@101: Chris@101: #else //!defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED) Chris@101: Chris@101: #include Chris@101: Chris@101: namespace boost { Chris@101: namespace move_detail { Chris@101: Chris@101: template Chris@101: inline typename ::boost::move_detail::enable_if_c Chris@101: < ::boost::move_detail::is_lvalue_reference::value Chris@101: , T&>::type Chris@101: move_return(T& x) BOOST_NOEXCEPT Chris@101: { Chris@101: return x; Chris@101: } Chris@101: Chris@101: template Chris@101: inline typename ::boost::move_detail::enable_if_c Chris@101: < !::boost::move_detail::is_lvalue_reference::value Chris@101: , Ret && >::type Chris@101: move_return(T&& t) BOOST_NOEXCEPT Chris@101: { Chris@101: return static_cast< Ret&& >(t); Chris@101: } Chris@101: Chris@101: } //namespace move_detail { Chris@101: } //namespace boost { Chris@101: Chris@101: #define BOOST_MOVE_RET(RET_TYPE, REF)\ Chris@101: boost::move_detail::move_return< RET_TYPE >(REF) Chris@101: // Chris@101: Chris@101: #endif //!defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED) Chris@101: Chris@101: //!This macro is used to achieve portable optimal move constructors. Chris@101: //! Chris@101: //!When implementing the move constructor, in C++03 compilers the moved-from argument must be Chris@101: //!cast to the base type before calling `::boost::move()` due to rvalue reference limitations. Chris@101: //! Chris@101: //!In C++11 compilers the cast from a rvalue reference of a derived type to a rvalue reference of Chris@101: //!a base type is implicit. Chris@101: #define BOOST_MOVE_BASE(BASE_TYPE, ARG) \ Chris@101: ::boost::move((BASE_TYPE&)(ARG)) Chris@101: // Chris@101: Chris@101: namespace boost { Chris@101: namespace move_detail { Chris@101: Chris@101: template< class T> struct forward_type { typedef T type; }; Chris@101: Chris@101: }} Chris@16: Chris@16: #endif //BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: Chris@16: #include Chris@16: Chris@16: #endif //#ifndef BOOST_MOVE_CORE_HPP