diff options
author | Chanho Park <chanho61.park@samsung.com> | 2014-12-11 18:55:56 +0900 |
---|---|---|
committer | Chanho Park <chanho61.park@samsung.com> | 2014-12-11 18:55:56 +0900 |
commit | 08c1e93fa36a49f49325a07fe91ff92c964c2b6c (patch) | |
tree | 7a7053ceb8874b28ec4b868d4c49b500008a102e /boost/move | |
parent | bb4dd8289b351fae6b55e303f189127a394a1edd (diff) | |
download | boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.gz boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.bz2 boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.zip |
Imported Upstream version 1.57.0upstream/1.57.0
Diffstat (limited to 'boost/move')
-rw-r--r-- | boost/move/algorithm.hpp | 274 | ||||
-rw-r--r-- | boost/move/core.hpp | 446 | ||||
-rw-r--r-- | boost/move/default_delete.hpp | 187 | ||||
-rw-r--r-- | boost/move/detail/config_begin.hpp | 18 | ||||
-rw-r--r-- | boost/move/detail/config_end.hpp | 12 | ||||
-rw-r--r-- | boost/move/detail/meta_utils.hpp | 476 | ||||
-rw-r--r-- | boost/move/detail/move_helpers.hpp (renamed from boost/move/move_helpers.hpp) | 66 | ||||
-rw-r--r-- | boost/move/detail/unique_ptr_meta_utils.hpp | 583 | ||||
-rw-r--r-- | boost/move/detail/workaround.hpp | 26 | ||||
-rw-r--r-- | boost/move/iterator.hpp | 304 | ||||
-rw-r--r-- | boost/move/make_unique.hpp | 619 | ||||
-rw-r--r-- | boost/move/move.hpp | 1264 | ||||
-rw-r--r-- | boost/move/traits.hpp | 72 | ||||
-rw-r--r-- | boost/move/unique_ptr.hpp | 855 | ||||
-rw-r--r-- | boost/move/utility.hpp | 141 | ||||
-rw-r--r-- | boost/move/utility_core.hpp | 295 |
16 files changed, 4345 insertions, 1293 deletions
diff --git a/boost/move/algorithm.hpp b/boost/move/algorithm.hpp new file mode 100644 index 0000000000..f5f4b81209 --- /dev/null +++ b/boost/move/algorithm.hpp @@ -0,0 +1,274 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2012. +// 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_ALGORITHM_HPP +#define BOOST_MOVE_ALGORITHM_HPP + +#include <boost/move/detail/config_begin.hpp> + +#include <boost/move/utility_core.hpp> +#include <boost/move/iterator.hpp> +#include <boost/detail/no_exceptions_support.hpp> + +#include <algorithm> //copy, copy_backward +#include <memory> //uninitialized_copy + +namespace boost { + +////////////////////////////////////////////////////////////////////////////// +// +// move +// +////////////////////////////////////////////////////////////////////////////// + +#if !defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE) + + //! <b>Effects</b>: Moves elements in the range [first,last) into the range [result,result + (last - + //! first)) starting from first and proceeding to last. For each non-negative integer n < (last-first), + //! performs *(result + n) = ::boost::move (*(first + n)). + //! + //! <b>Effects</b>: result + (last - first). + //! + //! <b>Requires</b>: result shall not be in the range [first,last). + //! + //! <b>Complexity</b>: Exactly last - first move assignments. + template <typename I, // I models InputIterator + typename O> // O models OutputIterator + O move(I f, I l, O result) + { + while (f != l) { + *result = ::boost::move(*f); + ++f; ++result; + } + return result; + } + + ////////////////////////////////////////////////////////////////////////////// + // + // move_backward + // + ////////////////////////////////////////////////////////////////////////////// + + //! <b>Effects</b>: Moves elements in the range [first,last) into the range + //! [result - (last-first),result) starting from last - 1 and proceeding to + //! first. For each positive integer n <= (last - first), + //! performs *(result - n) = ::boost::move(*(last - n)). + //! + //! <b>Requires</b>: result shall not be in the range [first,last). + //! + //! <b>Returns</b>: result - (last - first). + //! + //! <b>Complexity</b>: Exactly last - first assignments. + template <typename I, // I models BidirectionalIterator + typename O> // O models BidirectionalIterator + O move_backward(I f, I l, O result) + { + while (f != l) { + --l; --result; + *result = ::boost::move(*l); + } + return result; + } + +#else + + using ::std::move_backward; + +#endif //!defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE) + +////////////////////////////////////////////////////////////////////////////// +// +// uninitialized_move +// +////////////////////////////////////////////////////////////////////////////// + +//! <b>Effects</b>: +//! \code +//! for (; first != last; ++result, ++first) +//! new (static_cast<void*>(&*result)) +//! typename iterator_traits<ForwardIterator>::value_type(boost::move(*first)); +//! \endcode +//! +//! <b>Returns</b>: result +template + <typename I, // I models InputIterator + typename F> // F models ForwardIterator +F uninitialized_move(I f, I l, F r + /// @cond +// ,typename ::boost::move_detail::enable_if<has_move_emulation_enabled<typename std::iterator_traits<I>::value_type> >::type* = 0 + /// @endcond + ) +{ + typedef typename std::iterator_traits<I>::value_type input_value_type; + + F back = r; + BOOST_TRY{ + while (f != l) { + void * const addr = static_cast<void*>(::boost::move_detail::addressof(*r)); + ::new(addr) input_value_type(::boost::move(*f)); + ++f; ++r; + } + } + BOOST_CATCH(...){ + for (; back != r; ++back){ + back->~input_value_type(); + } + BOOST_RETHROW; + } + BOOST_CATCH_END + return r; +} + +/// @cond +/* +template + <typename I, // I models InputIterator + typename F> // F models ForwardIterator +F uninitialized_move(I f, I l, F r, + typename ::boost::move_detail::disable_if<has_move_emulation_enabled<typename std::iterator_traits<I>::value_type> >::type* = 0) +{ + return std::uninitialized_copy(f, l, r); +} +*/ + +////////////////////////////////////////////////////////////////////////////// +// +// uninitialized_copy_or_move +// +////////////////////////////////////////////////////////////////////////////// + +namespace move_detail { + +template +<typename I, // I models InputIterator +typename F> // F models ForwardIterator +inline F uninitialized_move_move_iterator(I f, I l, F r +// ,typename ::boost::move_detail::enable_if< has_move_emulation_enabled<typename I::value_type> >::type* = 0 +) +{ + return ::boost::uninitialized_move(f, l, r); +} +/* +template +<typename I, // I models InputIterator +typename F> // F models ForwardIterator +F uninitialized_move_move_iterator(I f, I l, F r, + typename ::boost::move_detail::disable_if< has_move_emulation_enabled<typename I::value_type> >::type* = 0) +{ + return std::uninitialized_copy(f.base(), l.base(), r); +} +*/ +} //namespace move_detail { + +template +<typename I, // I models InputIterator +typename F> // F models ForwardIterator +inline F uninitialized_copy_or_move(I f, I l, F r, + typename ::boost::move_detail::enable_if< move_detail::is_move_iterator<I> >::type* = 0) +{ + return ::boost::move_detail::uninitialized_move_move_iterator(f, l, r); +} + +////////////////////////////////////////////////////////////////////////////// +// +// copy_or_move +// +////////////////////////////////////////////////////////////////////////////// + +namespace move_detail { + +template +<typename I, // I models InputIterator +typename F> // F models ForwardIterator +inline F move_move_iterator(I f, I l, F r +// ,typename ::boost::move_detail::enable_if< has_move_emulation_enabled<typename I::value_type> >::type* = 0 +) +{ + return ::boost::move(f, l, r); +} +/* +template +<typename I, // I models InputIterator +typename F> // F models ForwardIterator +F move_move_iterator(I f, I l, F r, + typename ::boost::move_detail::disable_if< has_move_emulation_enabled<typename I::value_type> >::type* = 0) +{ + return std::copy(f.base(), l.base(), r); +} +*/ + +} //namespace move_detail { + +template +<typename I, // I models InputIterator +typename F> // F models ForwardIterator +inline F copy_or_move(I f, I l, F r, + typename ::boost::move_detail::enable_if< move_detail::is_move_iterator<I> >::type* = 0) +{ + return ::boost::move_detail::move_move_iterator(f, l, r); +} + +/// @endcond + +//! <b>Effects</b>: +//! \code +//! for (; first != last; ++result, ++first) +//! new (static_cast<void*>(&*result)) +//! typename iterator_traits<ForwardIterator>::value_type(*first); +//! \endcode +//! +//! <b>Returns</b>: result +//! +//! <b>Note</b>: This function is provided because +//! <i>std::uninitialized_copy</i> from some STL implementations +//! is not compatible with <i>move_iterator</i> +template +<typename I, // I models InputIterator +typename F> // F models ForwardIterator +inline F uninitialized_copy_or_move(I f, I l, F r + /// @cond + ,typename ::boost::move_detail::disable_if< move_detail::is_move_iterator<I> >::type* = 0 + /// @endcond + ) +{ + return std::uninitialized_copy(f, l, r); +} + +//! <b>Effects</b>: +//! \code +//! for (; first != last; ++result, ++first) +//! *result = *first; +//! \endcode +//! +//! <b>Returns</b>: result +//! +//! <b>Note</b>: This function is provided because +//! <i>std::uninitialized_copy</i> from some STL implementations +//! is not compatible with <i>move_iterator</i> +template +<typename I, // I models InputIterator +typename F> // F models ForwardIterator +inline F copy_or_move(I f, I l, F r + /// @cond + ,typename ::boost::move_detail::disable_if< move_detail::is_move_iterator<I> >::type* = 0 + /// @endcond + ) +{ + return std::copy(f, l, r); +} + +} //namespace boost { + +#include <boost/move/detail/config_end.hpp> + +#endif //#ifndef BOOST_MOVE_ALGORITHM_HPP diff --git a/boost/move/core.hpp b/boost/move/core.hpp new file mode 100644 index 0000000000..4728a71405 --- /dev/null +++ b/boost/move/core.hpp @@ -0,0 +1,446 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2012. +// 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 +//! This header implements macros to define movable classes and +//! move-aware functions + +#ifndef BOOST_MOVE_CORE_HPP +#define BOOST_MOVE_CORE_HPP + +#include <boost/move/detail/config_begin.hpp> + +//boost_move_no_copy_constructor_or_assign typedef +//used to detect noncopyable types for other Boost libraries. +#if defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + #define BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE) \ + private:\ + TYPE(TYPE &);\ + TYPE& operator=(TYPE &);\ + public:\ + typedef int boost_move_no_copy_constructor_or_assign; \ + private:\ + // +#else + #define BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE) \ + public:\ + TYPE(TYPE const &) = delete;\ + TYPE& operator=(TYPE const &) = delete;\ + public:\ + typedef int boost_move_no_copy_constructor_or_assign; \ + private:\ + // +#endif //BOOST_NO_CXX11_DELETED_FUNCTIONS + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED) + + #include <boost/move/detail/meta_utils.hpp> + + //Move emulation rv breaks standard aliasing rules so add workarounds for some compilers + #if defined(__GNUC__) && (__GNUC__ >= 4) && \ + (\ + defined(BOOST_GCC) || \ + (defined(BOOST_INTEL) && (BOOST_INTEL_CXX_VERSION >= 1300)) \ + ) + #define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS __attribute__((__may_alias__)) + #else + #define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS + #endif + + namespace boost { + + ////////////////////////////////////////////////////////////////////////////// + // + // struct rv + // + ////////////////////////////////////////////////////////////////////////////// + template <class T> + class rv + : public ::boost::move_detail::if_c + < ::boost::move_detail::is_class_or_union<T>::value + , T + , ::boost::move_detail::nat + >::type + { + rv(); + ~rv() throw(); + rv(rv const&); + void operator=(rv const&); + } BOOST_MOVE_ATTRIBUTE_MAY_ALIAS; + + + ////////////////////////////////////////////////////////////////////////////// + // + // is_rv + // + ////////////////////////////////////////////////////////////////////////////// + + namespace move_detail { + + template <class T> + struct is_rv + //Derive from integral constant because some Boost code assummes it has + //a "type" internal typedef + : integral_constant<bool, ::boost::move_detail::is_rv_impl<T>::value > + {}; + + } //namespace move_detail { + + ////////////////////////////////////////////////////////////////////////////// + // + // has_move_emulation_enabled + // + ////////////////////////////////////////////////////////////////////////////// + template<class T> + struct has_move_emulation_enabled + : ::boost::move_detail::has_move_emulation_enabled_impl<T> + {}; + + } //namespace boost { + + #define BOOST_RV_REF(TYPE)\ + ::boost::rv< TYPE >& \ + // + + #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ + ::boost::rv< TYPE<ARG1, ARG2> >& \ + // + + #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ + ::boost::rv< TYPE<ARG1, ARG2, ARG3> >& \ + // + + #define BOOST_RV_REF_BEG\ + ::boost::rv< \ + // + + #define BOOST_RV_REF_END\ + >& \ + // + + #define BOOST_FWD_REF(TYPE)\ + const TYPE & \ + // + + #define BOOST_COPY_ASSIGN_REF(TYPE)\ + const ::boost::rv< TYPE >& \ + // + + #define BOOST_COPY_ASSIGN_REF_BEG \ + const ::boost::rv< \ + // + + #define BOOST_COPY_ASSIGN_REF_END \ + >& \ + // + + #define BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ + const ::boost::rv< TYPE<ARG1, ARG2> >& \ + // + + #define BOOST_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ + const ::boost::rv< TYPE<ARG1, ARG2, ARG3> >& \ + // + + #define BOOST_CATCH_CONST_RLVALUE(TYPE)\ + const ::boost::rv< TYPE >& \ + // + + namespace boost { + namespace move_detail { + + template <class Ret, class T> + inline typename ::boost::move_detail::enable_if_c + < ::boost::move_detail::is_lvalue_reference<Ret>::value || + !::boost::has_move_emulation_enabled<T>::value + , T&>::type + move_return(T& x) BOOST_NOEXCEPT + { + return x; + } + + template <class Ret, class T> + inline typename ::boost::move_detail::enable_if_c + < !::boost::move_detail::is_lvalue_reference<Ret>::value && + ::boost::has_move_emulation_enabled<T>::value + , ::boost::rv<T>&>::type + move_return(T& x) BOOST_NOEXCEPT + { + return *static_cast< ::boost::rv<T>* >(::boost::move_detail::addressof(x)); + } + + template <class Ret, class T> + inline typename ::boost::move_detail::enable_if_c + < !::boost::move_detail::is_lvalue_reference<Ret>::value && + ::boost::has_move_emulation_enabled<T>::value + , ::boost::rv<T>&>::type + move_return(::boost::rv<T>& x) BOOST_NOEXCEPT + { + return x; + } + + } //namespace move_detail { + } //namespace boost { + + #define BOOST_MOVE_RET(RET_TYPE, REF)\ + boost::move_detail::move_return< RET_TYPE >(REF) + // + + ////////////////////////////////////////////////////////////////////////////// + // + // BOOST_MOVABLE_BUT_NOT_COPYABLE + // + ////////////////////////////////////////////////////////////////////////////// + #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\ + BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\ + public:\ + operator ::boost::rv<TYPE>&() \ + { return *static_cast< ::boost::rv<TYPE>* >(this); }\ + operator const ::boost::rv<TYPE>&() const \ + { return *static_cast<const ::boost::rv<TYPE>* >(this); }\ + private:\ + // + + ////////////////////////////////////////////////////////////////////////////// + // + // BOOST_COPYABLE_AND_MOVABLE + // + ////////////////////////////////////////////////////////////////////////////// + + #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\ + public:\ + TYPE& operator=(TYPE &t)\ + { this->operator=(static_cast<const ::boost::rv<TYPE> &>(const_cast<const TYPE &>(t))); return *this;}\ + public:\ + operator ::boost::rv<TYPE>&() \ + { return *static_cast< ::boost::rv<TYPE>* >(this); }\ + operator const ::boost::rv<TYPE>&() const \ + { return *static_cast<const ::boost::rv<TYPE>* >(this); }\ + private:\ + // + + #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\ + public:\ + operator ::boost::rv<TYPE>&() \ + { return *static_cast< ::boost::rv<TYPE>* >(this); }\ + operator const ::boost::rv<TYPE>&() const \ + { return *static_cast<const ::boost::rv<TYPE>* >(this); }\ + private:\ + // + + namespace boost{ + namespace move_detail{ + + template< class T> + struct forward_type + { typedef const T &type; }; + + template< class T> + struct forward_type< boost::rv<T> > + { typedef T type; }; + + }} + +#else //BOOST_NO_CXX11_RVALUE_REFERENCES + + //Compiler workaround detection + #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) + #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 5) && !defined(__clang__) + //Pre-standard rvalue binding rules + #define BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES + #elif defined(_MSC_VER) && (_MSC_VER == 1600) + //Standard rvalue binding rules but with some bugs + #define BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG + #define BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG + //Use standard library for MSVC to avoid namespace issues as + //some move calls in the STL are not fully qualified. + //#define BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE + #elif defined(_MSC_VER) && (_MSC_VER == 1700) + #define BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG + #endif + #endif + + //! This macro marks a type as movable but not copyable, disabling copy construction + //! and assignment. The user will need to write a move constructor/assignment as explained + //! in the documentation to fully write a movable but not copyable class. + #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\ + BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\ + public:\ + typedef int boost_move_emulation_t;\ + // + + //! This macro marks a type as copyable and movable. + //! The user will need to write a move constructor/assignment and a copy assignment + //! as explained in the documentation to fully write a copyable and movable class. + #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\ + // + + #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) + #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\ + // + #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED) + + namespace boost { + + //!This trait yields to a compile-time true boolean if T was marked as + //!BOOST_MOVABLE_BUT_NOT_COPYABLE or BOOST_COPYABLE_AND_MOVABLE and + //!rvalue references are not available on the platform. False otherwise. + template<class T> + struct has_move_emulation_enabled + { + static const bool value = false; + }; + + } //namespace boost{ + + //!This macro is used to achieve portable syntax in move + //!constructors and assignments for classes marked as + //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE + #define BOOST_RV_REF(TYPE)\ + TYPE && \ + // + + //!This macro is used to achieve portable syntax in move + //!constructors and assignments for template classes marked as + //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE. + //!As macros have problems with comma-separated template arguments, + //!the template argument must be preceded with BOOST_RV_REF_BEG + //!and ended with BOOST_RV_REF_END + #define BOOST_RV_REF_BEG\ + \ + // + + //!This macro is used to achieve portable syntax in move + //!constructors and assignments for template classes marked as + //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE. + //!As macros have problems with comma-separated template arguments, + //!the template argument must be preceded with BOOST_RV_REF_BEG + //!and ended with BOOST_RV_REF_END + #define BOOST_RV_REF_END\ + && \ + + //!This macro is used to achieve portable syntax in copy + //!assignment for classes marked as BOOST_COPYABLE_AND_MOVABLE. + #define BOOST_COPY_ASSIGN_REF(TYPE)\ + const TYPE & \ + // + + //! This macro is used to implement portable perfect forwarding + //! as explained in the documentation. + #define BOOST_FWD_REF(TYPE)\ + TYPE && \ + // + + #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) + + #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ + TYPE<ARG1, ARG2> && \ + // + + #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ + TYPE<ARG1, ARG2, ARG3> && \ + // + + #define BOOST_COPY_ASSIGN_REF_BEG \ + const \ + // + + #define BOOST_COPY_ASSIGN_REF_END \ + & \ + // + + #define BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ + const TYPE<ARG1, ARG2> & \ + // + + #define BOOST_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ + const TYPE<ARG1, ARG2, ARG3>& \ + // + + #define BOOST_CATCH_CONST_RLVALUE(TYPE)\ + const TYPE & \ + // + + + #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED) + + #if !defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED) + + //!This macro is used to achieve portable move return semantics. + //!The C++11 Standard allows implicit move returns when the object to be returned + //!is designated by a lvalue and: + //! - The criteria for elision of a copy operation are met OR + //! - The criteria would be met save for the fact that the source object is a function parameter + //! + //!For C++11 conforming compilers this macros only yields to REF: + //! <code>return BOOST_MOVE_RET(RET_TYPE, REF);</code> -> <code>return REF;</code> + //! + //!For compilers without rvalue references + //!this macro does an explicit move if the move emulation is activated + //!and the return type (RET_TYPE) is not a reference. + //! + //!For non-conforming compilers with rvalue references like Visual 2010 & 2012, + //!an explicit move is performed if RET_TYPE is not a reference. + //! + //! <b>Caution</b>: When using this macro in non-conforming or C++03 + //!compilers, a move will be performed even if the C++11 standard does not allow it + //!(e.g. returning a static variable). The user is responsible for using this macro + //!only to return local objects that met C++11 criteria. + #define BOOST_MOVE_RET(RET_TYPE, REF)\ + REF + // + + #else //!defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED) + + #include <boost/move/detail/meta_utils.hpp> + + namespace boost { + namespace move_detail { + + template <class Ret, class T> + inline typename ::boost::move_detail::enable_if_c + < ::boost::move_detail::is_lvalue_reference<Ret>::value + , T&>::type + move_return(T& x) BOOST_NOEXCEPT + { + return x; + } + + template <class Ret, class T> + inline typename ::boost::move_detail::enable_if_c + < !::boost::move_detail::is_lvalue_reference<Ret>::value + , Ret && >::type + move_return(T&& t) BOOST_NOEXCEPT + { + return static_cast< Ret&& >(t); + } + + } //namespace move_detail { + } //namespace boost { + + #define BOOST_MOVE_RET(RET_TYPE, REF)\ + boost::move_detail::move_return< RET_TYPE >(REF) + // + + #endif //!defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED) + + namespace boost { + namespace move_detail { + + template< class T> struct forward_type { typedef T type; }; + + }} + +#endif //BOOST_NO_CXX11_RVALUE_REFERENCES + +#include <boost/move/detail/config_end.hpp> + +#endif //#ifndef BOOST_MOVE_CORE_HPP diff --git a/boost/move/default_delete.hpp b/boost/move/default_delete.hpp new file mode 100644 index 0000000000..d8494e8adb --- /dev/null +++ b/boost/move/default_delete.hpp @@ -0,0 +1,187 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2014-2014. 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. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_MOVE_DEFAULT_DELETE_HPP_INCLUDED +#define BOOST_MOVE_DEFAULT_DELETE_HPP_INCLUDED + +#include <boost/move/detail/config_begin.hpp> +#include <boost/move/detail/workaround.hpp> +#include <boost/move/detail/unique_ptr_meta_utils.hpp> +#include <boost/move/utility_core.hpp> +#include <boost/static_assert.hpp> + +#include <cstddef> //For std::size_t,std::nullptr_t + +//!\file +//! Describes the default deleter (destruction policy) of <tt>unique_ptr</tt>: <tt>default_delete</tt>. + +namespace boost{ +namespace move_upd { + +namespace bmupmu = ::boost::move_upmu; + +//////////////////////////////////////// +//// enable_def_del +//////////////////////////////////////// + +//compatible with a pointer type T*: +//When either Y* is convertible to T* +//Y is U[N] and T is U cv [] +template<class U, class T> +struct def_del_compatible_cond + : bmupmu::is_convertible<U*, T*> +{}; + +template<class U, class T, std::size_t N> +struct def_del_compatible_cond<U[N], T[]> + : def_del_compatible_cond<U[], T[]> +{}; + +template<class U, class T, class Type = bmupmu::nat> +struct enable_def_del + : bmupmu::enable_if_c<def_del_compatible_cond<U, T>::value, Type> +{}; + +//////////////////////////////////////// +//// enable_defdel_call +//////////////////////////////////////// + +//When 2nd is T[N], 1st(*)[N] shall be convertible to T(*)[N]; +//When 2nd is T[], 1st(*)[] shall be convertible to T(*)[]; +//Otherwise, 1st* shall be convertible to 2nd*. + +template<class U, class T, class Type = bmupmu::nat> +struct enable_defdel_call + : public enable_def_del<U, T, Type> +{}; + +template<class U, class T, class Type> +struct enable_defdel_call<U, T[], Type> + : public enable_def_del<U[], T[], Type> +{}; + +template<class U, class T, class Type, std::size_t N> +struct enable_defdel_call<U, T[N], Type> + : public enable_def_del<U[N], T[N], Type> +{}; + +//////////////////////////////////////// +//// Some bool literal zero conversion utilities +//////////////////////////////////////// + +struct bool_conversion {int for_bool; int for_arg(); }; +typedef int bool_conversion::* explicit_bool_arg; + +#if !defined(BOOST_NO_CXX11_NULLPTR) && !defined(BOOST_NO_CXX11_DECLTYPE) + typedef decltype(nullptr) nullptr_type; +#elif !defined(BOOST_NO_CXX11_NULLPTR) + typedef std::nullptr_t nullptr_type; +#else + typedef int (bool_conversion::*nullptr_type)(); +#endif + +} //namespace move_upd { + +namespace movelib { + +namespace bmupd = boost::move_upd; +namespace bmupmu = ::boost::move_upmu; + +//!The class template <tt>default_delete</tt> serves as the default deleter +//!(destruction policy) for the class template <tt>unique_ptr</tt>. +//! +//! \tparam T The type to be deleted. It may be an incomplete type +template <class T> +struct default_delete +{ + //! Default constructor. + //! + BOOST_CONSTEXPR default_delete() + //Avoid "defaulted on its first declaration must not have an exception-specification" error for GCC 4.6 + #if !defined(BOOST_GCC) || (BOOST_GCC < 40600 && BOOST_GCC >= 40700) || defined(BOOST_MOVE_DOXYGEN_INVOKED) + BOOST_NOEXCEPT + #endif + #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || defined(BOOST_MOVE_DOXYGEN_INVOKED) + = default; + #else + {}; + #endif + + #if defined(BOOST_MOVE_DOXYGEN_INVOKED) + default_delete(const default_delete&) BOOST_NOEXCEPT = default; + default_delete &operator=(const default_delete&) BOOST_NOEXCEPT = default; + #else + typedef typename bmupmu::remove_extent<T>::type element_type; + #endif + + //! <b>Effects</b>: Constructs a default_delete object from another <tt>default_delete<U></tt> object. + //! + //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless: + //! - If T is not an array type and U* is implicitly convertible to T*. + //! - If T is an array type and U* is a more CV qualified pointer to remove_extent<T>::type. + template <class U> + default_delete(const default_delete<U>& + BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_def_del<U BOOST_MOVE_I T>::type* =0) + ) BOOST_NOEXCEPT + { + //If T is not an array type, U derives from T + //and T has no virtual destructor, then you have a problem + BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor<default_delete, U>::value )); + } + + //! <b>Effects</b>: Constructs a default_delete object from another <tt>default_delete<U></tt> object. + //! + //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless: + //! - If T is not an array type and U* is implicitly convertible to T*. + //! - If T is an array type and U* is a more CV qualified pointer to remove_extent<T>::type. + template <class U> + BOOST_MOVE_DOC1ST(default_delete&, + typename bmupd::enable_def_del<U BOOST_MOVE_I T BOOST_MOVE_I default_delete &>::type) + operator=(const default_delete<U>&) BOOST_NOEXCEPT + { + //If T is not an array type, U derives from T + //and T has no virtual destructor, then you have a problem + BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor<default_delete, U>::value )); + return *this; + } + + //! <b>Effects</b>: if T is not an array type, calls <tt>delete</tt> on static_cast<T*>(ptr), + //! otherwise calls <tt>delete[]</tt> on static_cast<remove_extent<T>::type*>(ptr). + //! + //! <b>Remarks</b>: If U is an incomplete type, the program is ill-formed. + //! This operator shall not participate in overload resolution unless: + //! - T is not an array type and U* is convertible to T*, OR + //! - T is an array type, and remove_cv<U>::type is the same type as + //! remove_cv<remove_extent<T>::type>::type and U* is convertible to remove_extent<T>::type*. + template <class U> + BOOST_MOVE_DOC1ST(void, typename bmupd::enable_defdel_call<U BOOST_MOVE_I T BOOST_MOVE_I void>::type) + operator()(U* ptr) const BOOST_NOEXCEPT + { + //U must be a complete type + BOOST_STATIC_ASSERT(sizeof(U) > 0); + //If T is not an array type, U derives from T + //and T has no virtual destructor, then you have a problem + BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor<default_delete, U>::value )); + element_type * const p = static_cast<element_type*>(ptr); + bmupmu::is_array<T>::value ? delete [] p : delete p; + } + + //! <b>Effects</b>: Same as <tt>(*this)(static_cast<element_type*>(nullptr))</tt>. + //! + void operator()(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) const BOOST_NOEXCEPT + { BOOST_STATIC_ASSERT(sizeof(element_type) > 0); } +}; + +} //namespace movelib { +} //namespace boost{ + +#include <boost/move/detail/config_end.hpp> + +#endif //#ifndef BOOST_MOVE_DEFAULT_DELETE_HPP_INCLUDED diff --git a/boost/move/detail/config_begin.hpp b/boost/move/detail/config_begin.hpp new file mode 100644 index 0000000000..edc25d4d1c --- /dev/null +++ b/boost/move/detail/config_begin.hpp @@ -0,0 +1,18 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2012. 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. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_CONFIG_HPP +#include <boost/config.hpp> +#endif + +#ifdef BOOST_MSVC +# pragma warning (push) +# pragma warning (disable : 4996) // "function": was declared deprecated (_CRT_SECURE_NO_DEPRECATE/_SCL_SECURE_NO_WARNINGS) +# pragma warning (disable : 4675) // "function": resolved overload was found by argument-dependent lookup +#endif diff --git a/boost/move/detail/config_end.hpp b/boost/move/detail/config_end.hpp new file mode 100644 index 0000000000..71a99e93c9 --- /dev/null +++ b/boost/move/detail/config_end.hpp @@ -0,0 +1,12 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2012. 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. +// +////////////////////////////////////////////////////////////////////////////// +#if defined BOOST_MSVC +# pragma warning (pop) +#endif diff --git a/boost/move/detail/meta_utils.hpp b/boost/move/detail/meta_utils.hpp new file mode 100644 index 0000000000..0df00864ae --- /dev/null +++ b/boost/move/detail/meta_utils.hpp @@ -0,0 +1,476 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2012. +// 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 + +#include <boost/move/detail/config_begin.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 { + +////////////////////////////////////// +// nat +////////////////////////////////////// +struct nat{}; + +////////////////////////////////////// +// natify +////////////////////////////////////// +template <class T> struct natify{}; + +////////////////////////////////////// +// if_c +////////////////////////////////////// +template<bool C, typename T1, typename T2> +struct if_c +{ + typedef T1 type; +}; + +template<typename T1, typename T2> +struct if_c<false,T1,T2> +{ + typedef T2 type; +}; + +////////////////////////////////////// +// if_ +////////////////////////////////////// +template<typename T1, typename T2, typename T3> +struct if_ +{ + typedef typename if_c<0 != T1::value, T2, T3>::type type; +}; + +//enable_if_ +template <bool B, class T = nat> +struct enable_if_c +{ + typedef T type; +}; + +////////////////////////////////////// +// enable_if_c +////////////////////////////////////// +template <class T> +struct enable_if_c<false, T> {}; + +////////////////////////////////////// +// enable_if +////////////////////////////////////// +template <class Cond, class T = nat> +struct enable_if : public enable_if_c<Cond::value, T> {}; + +////////////////////////////////////// +// disable_if +////////////////////////////////////// +template <class Cond, class T = nat> +struct disable_if : public enable_if_c<!Cond::value, T> {}; + +////////////////////////////////////// +// integral_constant +////////////////////////////////////// +template<class T, T v> +struct integral_constant +{ + static const T value = v; + typedef T value_type; + typedef integral_constant<T, v> type; +}; + +typedef integral_constant<bool, true > true_type; +typedef integral_constant<bool, false > false_type; + +////////////////////////////////////// +// identity +////////////////////////////////////// +template <class T> +struct identity +{ + typedef T type; +}; + +////////////////////////////////////// +// 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 + +////////////////////////////////////// +// 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_same +////////////////////////////////////// +template<class T, class U> +struct is_same +{ + static const bool value = false; +}; + +template<class T> +struct is_same<T, T> +{ + static const bool value = true; +}; + +////////////////////////////////////// +// 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; +}; + +////////////////////////////////////// +// is_class_or_union +////////////////////////////////////// +template<class T> +struct is_class_or_union +{ + struct twochar { char _[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_; + inline addr_impl_ref( T & v ): v_( v ) {} + inline operator T& () const { return v_; } + + private: + addr_impl_ref & operator=(const addr_impl_ref &); +}; + +template<class T> +struct addressof_impl +{ + static inline T * f( T & v, long ) + { + return reinterpret_cast<T*>( + &const_cast<char&>(reinterpret_cast<const volatile char &>(v))); + } + + static inline T * f( T * v, int ) + { return v; } +}; + +template<class T> +inline 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 + +////////////////////////////////////////////////////////////////////////////// +// +// 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 diff --git a/boost/move/move_helpers.hpp b/boost/move/detail/move_helpers.hpp index eaf51d651f..78d98ea416 100644 --- a/boost/move/move_helpers.hpp +++ b/boost/move/detail/move_helpers.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2010-2011. +// (C) Copyright Ion Gaztanaga 2010-2012. // 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) @@ -12,24 +12,15 @@ #ifndef BOOST_MOVE_MOVE_HELPERS_HPP #define BOOST_MOVE_MOVE_HELPERS_HPP -#include <boost/move/move.hpp> -#include <boost/type_traits/is_class.hpp> - -#if defined(BOOST_NO_RVALUE_REFERENCES) || (defined(_MSC_VER) && (_MSC_VER == 1600)) -#include <boost/type_traits/is_same.hpp> -#include <boost/utility/enable_if.hpp> -#endif -#if defined(BOOST_NO_RVALUE_REFERENCES) -#include <boost/mpl/if.hpp> -#endif +#include <boost/move/utility_core.hpp> +#include <boost/move/detail/meta_utils.hpp> +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) -#if defined(BOOST_NO_RVALUE_REFERENCES) -struct not_a_type; #define BOOST_MOVE_CATCH_CONST(U) \ - typename ::boost::mpl::if_< ::boost::is_class<U>, BOOST_CATCH_CONST_RLVALUE(U), const U &>::type + typename ::boost::move_detail::if_< ::boost::move_detail::is_class_or_union<U>, BOOST_CATCH_CONST_RLVALUE(U), const U &>::type #define BOOST_MOVE_CATCH_RVALUE(U)\ - typename ::boost::mpl::if_< ::boost::is_class<U>, BOOST_RV_REF(U), not_a_type>::type + typename ::boost::move_detail::if_< ::boost::move_detail::is_class_or_union<U>, BOOST_RV_REF(U), ::boost::move_detail::nat>::type #define BOOST_MOVE_CATCH_FWD(U) BOOST_FWD_REF(U) #else #define BOOST_MOVE_CATCH_CONST(U) const U & @@ -37,8 +28,7 @@ struct not_a_type; #define BOOST_MOVE_CATCH_FWD(U) U && #endif -#ifdef BOOST_NO_RVALUE_REFERENCES - +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES #define BOOST_MOVE_CONVERSION_AWARE_CATCH(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION)\ RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_CONST(TYPE) x)\ { return FWD_FUNCTION(static_cast<const TYPE&>(x)); }\ @@ -50,19 +40,19 @@ struct not_a_type; { return FWD_FUNCTION(const_cast<const TYPE &>(x)); }\ \ template<class BOOST_MOVE_TEMPL_PARAM>\ - typename ::boost::enable_if_c\ - < ::boost::is_class<TYPE>::value &&\ - ::boost::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>::value &&\ + typename ::boost::move_detail::enable_if_c\ + < ::boost::move_detail::is_class_or_union<TYPE>::value &&\ + ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>::value &&\ !::boost::has_move_emulation_enabled<BOOST_MOVE_TEMPL_PARAM>::value\ , RETURN_VALUE >::type\ PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u)\ { return FWD_FUNCTION(u); }\ \ template<class BOOST_MOVE_TEMPL_PARAM>\ - typename ::boost::enable_if_c\ - < (!::boost::is_class<BOOST_MOVE_TEMPL_PARAM>::value || \ + typename ::boost::move_detail::enable_if_c\ + < (!::boost::move_detail::is_class_or_union<BOOST_MOVE_TEMPL_PARAM>::value || \ !::boost::move_detail::is_rv<BOOST_MOVE_TEMPL_PARAM>::value) && \ - !::boost::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>::value \ + !::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>::value \ , RETURN_VALUE >::type\ PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u)\ {\ @@ -81,8 +71,8 @@ struct not_a_type; { return FWD_FUNCTION(::boost::move(x)); }\ \ template<class BOOST_MOVE_TEMPL_PARAM>\ - typename ::boost::enable_if_c\ - < !::boost::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>::value\ + typename ::boost::move_detail::enable_if_c\ + < !::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>::value\ , RETURN_VALUE >::type\ PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u)\ {\ @@ -104,9 +94,9 @@ struct not_a_type; #endif -#ifdef BOOST_NO_RVALUE_REFERENCES +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES -#define BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1)\ +#define BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\ RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_CONST(TYPE) x)\ { return FWD_FUNCTION(arg1, static_cast<const TYPE&>(x)); }\ \ @@ -117,19 +107,18 @@ struct not_a_type; { return FWD_FUNCTION(arg1, const_cast<const TYPE &>(x)); }\ \ template<class BOOST_MOVE_TEMPL_PARAM>\ - typename ::boost::enable_if_c\ - < ::boost::is_class<TYPE>::value &&\ - ::boost::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>::value &&\ + typename ::boost::move_detail::enable_if_c<\ + ::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>::value &&\ !::boost::has_move_emulation_enabled<BOOST_MOVE_TEMPL_PARAM>::value\ , RETURN_VALUE >::type\ PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u)\ { return FWD_FUNCTION(arg1, u); }\ \ template<class BOOST_MOVE_TEMPL_PARAM>\ - typename ::boost::enable_if_c\ - < (!::boost::is_class<BOOST_MOVE_TEMPL_PARAM>::value || \ - !::boost::move_detail::is_rv<BOOST_MOVE_TEMPL_PARAM>::value) && \ - !::boost::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>::value \ + typename ::boost::move_detail::enable_if_c<\ + !::boost::move_detail::is_rv<BOOST_MOVE_TEMPL_PARAM>::value && \ + !::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>::value && \ + !::boost::move_detail::is_convertible<BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO>::value \ , RETURN_VALUE >::type\ PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u)\ {\ @@ -140,7 +129,7 @@ struct not_a_type; #elif (defined(_MSC_VER) && (_MSC_VER == 1600)) -#define BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1)\ +#define BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\ RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_CONST(TYPE) x)\ { return FWD_FUNCTION(arg1, static_cast<const TYPE&>(x)); }\ \ @@ -148,8 +137,9 @@ struct not_a_type; { return FWD_FUNCTION(arg1, ::boost::move(x)); }\ \ template<class BOOST_MOVE_TEMPL_PARAM>\ - typename ::boost::enable_if_c\ - < !::boost::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>::value\ + typename ::boost::move_detail::enable_if_c\ + < !::boost::move_detail::is_same<TYPE, BOOST_MOVE_TEMPL_PARAM>::value && \ + !::boost::move_detail::is_convertible<BOOST_MOVE_TEMPL_PARAM, UNLESS_CONVERTIBLE_TO>::value \ , RETURN_VALUE >::type\ PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u)\ {\ @@ -160,7 +150,7 @@ struct not_a_type; #else -#define BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1)\ +#define BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(PUB_FUNCTION, TYPE, RETURN_VALUE, FWD_FUNCTION, ARG1, UNLESS_CONVERTIBLE_TO)\ RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_CONST(TYPE) x)\ { return FWD_FUNCTION(arg1, static_cast<const TYPE&>(x)); }\ \ diff --git a/boost/move/detail/unique_ptr_meta_utils.hpp b/boost/move/detail/unique_ptr_meta_utils.hpp new file mode 100644 index 0000000000..42fd27299f --- /dev/null +++ b/boost/move/detail/unique_ptr_meta_utils.hpp @@ -0,0 +1,583 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2012. +// 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_UNIQUE_PTR_DETAIL_META_UTILS_HPP +#define BOOST_MOVE_UNIQUE_PTR_DETAIL_META_UTILS_HPP + +#include <cstddef> //for std::size_t + +//Small meta-typetraits to support move + +namespace boost { + +namespace movelib { + +template <class T> +struct default_delete; + +} //namespace movelib { + +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES +//Forward declare boost::rv +template <class T> class rv; +#endif + +namespace move_upmu { + +////////////////////////////////////// +// nat +////////////////////////////////////// +struct nat{}; + +////////////////////////////////////// +// natify +////////////////////////////////////// +template <class T> struct natify{}; + +////////////////////////////////////// +// if_c +////////////////////////////////////// +template<bool C, typename T1, typename T2> +struct if_c +{ + typedef T1 type; +}; + +template<typename T1, typename T2> +struct if_c<false,T1,T2> +{ + typedef T2 type; +}; + +////////////////////////////////////// +// if_ +////////////////////////////////////// +template<typename T1, typename T2, typename T3> +struct if_ : if_c<0 != T1::value, T2, T3> +{}; + +//enable_if_ +template <bool B, class T = nat> +struct enable_if_c +{ + typedef T type; +}; + +////////////////////////////////////// +// enable_if_c +////////////////////////////////////// +template <class T> +struct enable_if_c<false, T> {}; + +////////////////////////////////////// +// enable_if +////////////////////////////////////// +template <class Cond, class T = nat> +struct enable_if : public enable_if_c<Cond::value, T> {}; + +////////////////////////////////////// +// 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_const +////////////////////////////////////// +template< class T > +struct remove_const +{ + typedef T type; +}; + +template< class T > +struct remove_const<const T> +{ + typedef T type; +}; + +////////////////////////////////////// +// remove_volatile +////////////////////////////////////// +template< class T > +struct remove_volatile +{ + typedef T type; +}; + +template< class T > +struct remove_volatile<volatile T> +{ + typedef T type; +}; + +////////////////////////////////////// +// remove_cv +////////////////////////////////////// +template< class T > +struct remove_cv +{ + typedef typename remove_volatile + <typename remove_const<T>::type>::type type; +}; + +////////////////////////////////////// +// remove_extent +////////////////////////////////////// +template<class T> +struct remove_extent +{ + typedef T type; +}; + +template<class T> +struct remove_extent<T[]> +{ + typedef T type; +}; + +template<class T, std::size_t N> +struct remove_extent<T[N]> +{ + typedef T type; +}; + +////////////////////////////////////// +// extent +////////////////////////////////////// + +template<class T, unsigned N = 0> +struct extent +{ + static const std::size_t value = 0; +}; + +template<class T> +struct extent<T[], 0> +{ + static const std::size_t value = 0; +}; + +template<class T, unsigned N> +struct extent<T[], N> +{ + static const std::size_t value = extent<T, N-1>::value; +}; + +template<class T, std::size_t N> +struct extent<T[N], 0> +{ + static const std::size_t value = N; +}; + +template<class T, std::size_t I, unsigned N> +struct extent<T[I], N> +{ + static const std::size_t value = extent<T, N-1>::value; +}; + +////////////////////////////////////// +// 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 const t_unreferenced t_unreferenced_const; + typedef typename add_lvalue_reference + <t_unreferenced_const>::type type; +}; + +////////////////////////////////////// +// is_same +////////////////////////////////////// +template<class T, class U> +struct is_same +{ + static const bool value = false; +}; + +template<class T> +struct is_same<T, T> +{ + static const bool value = true; +}; + +////////////////////////////////////// +// is_pointer +////////////////////////////////////// +template< class T > +struct is_pointer +{ + static const bool value = false; +}; + +template< class T > +struct is_pointer<T*> +{ + static const bool value = true; +}; + +////////////////////////////////////// +// is_reference +////////////////////////////////////// +template< class T > +struct is_reference +{ + static const bool value = false; +}; + +template< class T > +struct is_reference<T&> +{ + static const bool value = true; +}; + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +template< class T > +struct is_reference<T&&> +{ + static const bool value = true; +}; + +#endif + +////////////////////////////////////// +// 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; +}; + +////////////////////////////////////// +// is_array +////////////////////////////////////// +template<class T> +struct is_array +{ + static const bool value = false; +}; + +template<class T> +struct is_array<T[]> +{ + static const bool value = true; +}; + +template<class T, std::size_t N> +struct is_array<T[N]> +{ + static const bool value = true; +}; + +////////////////////////////////////// +// 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; +}; + +////////////////////////////////////// +// pointer_type +////////////////////////////////////// +template <class T, class D, bool = has_pointer_type<D>::value> +struct pointer_type_imp +{ + typedef typename D::pointer type; +}; + +template <class T, class D> +struct pointer_type_imp<T, D, false> +{ + typedef typename remove_extent<T>::type* type; +}; + +template <class T, class D> +struct pointer_type +{ + typedef typename pointer_type_imp + <typename remove_extent<T>::type, typename remove_reference<D>::type>::type type; +}; + +////////////////////////////////////// +// 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 + +////////////////////////////////////// +// is_unary_function +////////////////////////////////////// +#if defined(BOOST_MSVC) || defined(__BORLANDC_) +#define BOOST_MOVE_TT_DECL __cdecl +#else +#define BOOST_MOVE_TT_DECL +#endif + +#if defined(_MSC_EXTENSIONS) && !defined(__BORLAND__) && !defined(_WIN64) && !defined(_M_ARM) && !defined(UNDER_CE) +#define BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS +#endif + +template <typename T> +struct is_unary_function_impl +{ static const bool value = false; }; + +// avoid duplicate definitions of is_unary_function_impl +#ifndef BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS + +template <typename R> +struct is_unary_function_impl<R (*)()> +{ static const bool value = true; }; + +template <typename R> +struct is_unary_function_impl<R (*)(...)> +{ static const bool value = true; }; + +#else // BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS + +template <typename R> +struct is_unary_function_impl<R (__stdcall*)()> +{ static const bool value = true; }; + +#ifndef _MANAGED + +template <typename R> +struct is_unary_function_impl<R (__fastcall*)()> +{ static const bool value = true; }; + +#endif + +template <typename R> +struct is_unary_function_impl<R (__cdecl*)()> +{ static const bool value = true; }; + +template <typename R> +struct is_unary_function_impl<R (__cdecl*)(...)> +{ static const bool value = true; }; + +#endif + +// avoid duplicate definitions of is_unary_function_impl +#ifndef BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS + +template <typename R, class T0> +struct is_unary_function_impl<R (*)(T0)> +{ static const bool value = true; }; + +template <typename R, class T0> +struct is_unary_function_impl<R (*)(T0...)> +{ static const bool value = true; }; + +#else // BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS + +template <typename R, class T0> +struct is_unary_function_impl<R (__stdcall*)(T0)> +{ static const bool value = true; }; + +#ifndef _MANAGED + +template <typename R, class T0> +struct is_unary_function_impl<R (__fastcall*)(T0)> +{ static const bool value = true; }; + +#endif + +template <typename R, class T0> +struct is_unary_function_impl<R (__cdecl*)(T0)> +{ static const bool value = true; }; + +template <typename R, class T0> +struct is_unary_function_impl<R (__cdecl*)(T0...)> +{ static const bool value = true; }; + +#endif + +template <typename T> +struct is_unary_function_impl<T&> +{ static const bool value = false; }; + +template<typename T> +struct is_unary_function +{ static const bool value = is_unary_function_impl<T>::value; }; + +////////////////////////////////////// +// has_virtual_destructor +////////////////////////////////////// +#if (defined(BOOST_MSVC) && defined(BOOST_MSVC_FULL_VER) && (BOOST_MSVC_FULL_VER >=140050215))\ + || (defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1500)) +# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) +#elif defined(BOOST_CLANG) && defined(__has_feature) +# if __has_feature(has_virtual_destructor) +# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) +# endif +#elif defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3) && !defined(__GCCXML__))) && !defined(BOOST_CLANG) +# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) +#elif defined(__ghs__) && (__GHS_VERSION_NUMBER >= 600) +# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) +#elif defined(__CODEGEARC__) +# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) +#endif + +#ifdef BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR + template<class T> + struct has_virtual_destructor{ static const bool value = BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T); }; +#else + //If no intrinsic is available you trust the programmer knows what is doing + template<class T> + struct has_virtual_destructor{ static const bool value = true; }; +#endif + +////////////////////////////////////// +// missing_virtual_destructor +////////////////////////////////////// + +template< class T, class U + , bool enable = is_convertible< U*, T*>::value && + !is_array<T>::value && + !is_same<typename remove_cv<T>::type, void>::value && + !is_same<typename remove_cv<U>::type, typename remove_cv<T>::type>::value + > +struct missing_virtual_destructor_default_delete +{ static const bool value = !has_virtual_destructor<T>::value; }; + +template<class T, class U> +struct missing_virtual_destructor_default_delete<T, U, false> +{ static const bool value = false; }; + +template<class Deleter, class U> +struct missing_virtual_destructor +{ static const bool value = false; }; + +template<class T, class U> +struct missing_virtual_destructor< ::boost::movelib::default_delete<T>, U > + : missing_virtual_destructor_default_delete<T, U> +{}; + +} //namespace move_upmu { +} //namespace boost { + +#endif //#ifndef BOOST_MOVE_UNIQUE_PTR_DETAIL_META_UTILS_HPP diff --git a/boost/move/detail/workaround.hpp b/boost/move/detail/workaround.hpp new file mode 100644 index 0000000000..1bf879cbbc --- /dev/null +++ b/boost/move/detail/workaround.hpp @@ -0,0 +1,26 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2014-2014. 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/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_MOVE_DETAIL_WORKAROUND_HPP +#define BOOST_MOVE_DETAIL_WORKAROUND_HPP + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + #define BOOST_MOVE_PERFECT_FORWARDING +#endif + +//Macros for documentation purposes. For code, expands to the argument +#define BOOST_MOVE_IMPDEF(TYPE) TYPE +#define BOOST_MOVE_SEEDOC(TYPE) TYPE +#define BOOST_MOVE_DOC0PTR(TYPE) TYPE +#define BOOST_MOVE_DOC1ST(TYPE1, TYPE2) TYPE2 +#define BOOST_MOVE_I , +#define BOOST_MOVE_DOCIGN(T1) T1 + +#endif //#ifndef BOOST_MOVE_DETAIL_WORKAROUND_HPP diff --git a/boost/move/iterator.hpp b/boost/move/iterator.hpp new file mode 100644 index 0000000000..dda6f8339b --- /dev/null +++ b/boost/move/iterator.hpp @@ -0,0 +1,304 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2012. +// 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_ITERATOR_HPP +#define BOOST_MOVE_ITERATOR_HPP + +#include <boost/move/detail/config_begin.hpp> +#include <boost/move/utility_core.hpp> +#include <iterator> //std::iterator + +namespace boost { + +////////////////////////////////////////////////////////////////////////////// +// +// move_iterator +// +////////////////////////////////////////////////////////////////////////////// + +//! Class template move_iterator is an iterator adaptor with the same behavior +//! as the underlying iterator except that its dereference operator implicitly +//! converts the value returned by the underlying iterator's dereference operator +//! to an rvalue reference. Some generic algorithms can be called with move +//! iterators to replace copying with moving. +template <class It> +class move_iterator +{ + public: + typedef It iterator_type; + typedef typename std::iterator_traits<iterator_type>::value_type value_type; + #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_MOVE_DOXYGEN_INVOKED) + typedef value_type && reference; + #else + typedef typename ::boost::move_detail::if_ + < ::boost::has_move_emulation_enabled<value_type> + , ::boost::rv<value_type>& + , value_type & >::type reference; + #endif + typedef It pointer; + typedef typename std::iterator_traits<iterator_type>::difference_type difference_type; + typedef typename std::iterator_traits<iterator_type>::iterator_category iterator_category; + + move_iterator() + {} + + explicit move_iterator(It i) + : m_it(i) + {} + + template <class U> + move_iterator(const move_iterator<U>& u) + : m_it(u.base()) + {} + + iterator_type base() const + { return m_it; } + + reference operator*() const + { + #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) + return *m_it; + #else + return ::boost::move(*m_it); + #endif + } + + pointer operator->() const + { return m_it; } + + move_iterator& operator++() + { ++m_it; return *this; } + + move_iterator<iterator_type> operator++(int) + { move_iterator<iterator_type> tmp(*this); ++(*this); return tmp; } + + move_iterator& operator--() + { --m_it; return *this; } + + move_iterator<iterator_type> operator--(int) + { move_iterator<iterator_type> tmp(*this); --(*this); return tmp; } + + move_iterator<iterator_type> operator+ (difference_type n) const + { return move_iterator<iterator_type>(m_it + n); } + + move_iterator& operator+=(difference_type n) + { m_it += n; return *this; } + + move_iterator<iterator_type> operator- (difference_type n) const + { return move_iterator<iterator_type>(m_it - n); } + + move_iterator& operator-=(difference_type n) + { m_it -= n; return *this; } + + reference operator[](difference_type n) const + { + #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) + return m_it[n]; + #else + return ::boost::move(m_it[n]); + #endif + } + + friend bool operator==(const move_iterator& x, const move_iterator& y) + { return x.base() == y.base(); } + + friend bool operator!=(const move_iterator& x, const move_iterator& y) + { return x.base() != y.base(); } + + friend bool operator< (const move_iterator& x, const move_iterator& y) + { return x.base() < y.base(); } + + friend bool operator<=(const move_iterator& x, const move_iterator& y) + { return x.base() <= y.base(); } + + friend bool operator> (const move_iterator& x, const move_iterator& y) + { return x.base() > y.base(); } + + friend bool operator>=(const move_iterator& x, const move_iterator& y) + { return x.base() >= y.base(); } + + friend difference_type operator-(const move_iterator& x, const move_iterator& y) + { return x.base() - y.base(); } + + friend move_iterator operator+(difference_type n, const move_iterator& x) + { return move_iterator(x.base() + n); } + + private: + It m_it; +}; + +//is_move_iterator +namespace move_detail { + +template <class I> +struct is_move_iterator +{ + static const bool value = false; +}; + +template <class I> +struct is_move_iterator< ::boost::move_iterator<I> > +{ + static const bool value = true; +}; + +} //namespace move_detail { + +////////////////////////////////////////////////////////////////////////////// +// +// move_iterator +// +////////////////////////////////////////////////////////////////////////////// + +//! +//! <b>Returns</b>: move_iterator<It>(i). +template<class It> +inline move_iterator<It> make_move_iterator(const It &it) +{ return move_iterator<It>(it); } + +////////////////////////////////////////////////////////////////////////////// +// +// back_move_insert_iterator +// +////////////////////////////////////////////////////////////////////////////// + + +//! A move insert iterator that move constructs elements at the +//! back of a container +template <typename C> // C models Container +class back_move_insert_iterator +{ + C* container_m; + + public: + typedef C container_type; + typedef typename C::value_type value_type; + typedef typename C::reference reference; + typedef typename C::pointer pointer; + typedef typename C::difference_type difference_type; + typedef std::output_iterator_tag iterator_category; + + explicit back_move_insert_iterator(C& x) : container_m(&x) { } + + back_move_insert_iterator& operator=(reference x) + { container_m->push_back(boost::move(x)); return *this; } + + back_move_insert_iterator& operator=(BOOST_RV_REF(value_type) x) + { reference rx = x; return this->operator=(rx); } + + back_move_insert_iterator& operator*() { return *this; } + back_move_insert_iterator& operator++() { return *this; } + back_move_insert_iterator& operator++(int) { return *this; } +}; + +//! +//! <b>Returns</b>: back_move_insert_iterator<C>(x). +template <typename C> // C models Container +inline back_move_insert_iterator<C> back_move_inserter(C& x) +{ + return back_move_insert_iterator<C>(x); +} + +////////////////////////////////////////////////////////////////////////////// +// +// front_move_insert_iterator +// +////////////////////////////////////////////////////////////////////////////// + +//! A move insert iterator that move constructs elements int the +//! front of a container +template <typename C> // C models Container +class front_move_insert_iterator +{ + C* container_m; + +public: + typedef C container_type; + typedef typename C::value_type value_type; + typedef typename C::reference reference; + typedef typename C::pointer pointer; + typedef typename C::difference_type difference_type; + typedef std::output_iterator_tag iterator_category; + + explicit front_move_insert_iterator(C& x) : container_m(&x) { } + + front_move_insert_iterator& operator=(reference x) + { container_m->push_front(boost::move(x)); return *this; } + + front_move_insert_iterator& operator=(BOOST_RV_REF(value_type) x) + { reference rx = x; return this->operator=(rx); } + + front_move_insert_iterator& operator*() { return *this; } + front_move_insert_iterator& operator++() { return *this; } + front_move_insert_iterator& operator++(int) { return *this; } +}; + +//! +//! <b>Returns</b>: front_move_insert_iterator<C>(x). +template <typename C> // C models Container +inline front_move_insert_iterator<C> front_move_inserter(C& x) +{ + return front_move_insert_iterator<C>(x); +} + +////////////////////////////////////////////////////////////////////////////// +// +// insert_move_iterator +// +////////////////////////////////////////////////////////////////////////////// +template <typename C> // C models Container +class move_insert_iterator +{ + C* container_m; + typename C::iterator pos_; + + public: + typedef C container_type; + typedef typename C::value_type value_type; + typedef typename C::reference reference; + typedef typename C::pointer pointer; + typedef typename C::difference_type difference_type; + typedef std::output_iterator_tag iterator_category; + + explicit move_insert_iterator(C& x, typename C::iterator pos) + : container_m(&x), pos_(pos) + {} + + move_insert_iterator& operator=(reference x) + { + pos_ = container_m->insert(pos_, ::boost::move(x)); + ++pos_; + return *this; + } + + move_insert_iterator& operator=(BOOST_RV_REF(value_type) x) + { reference rx = x; return this->operator=(rx); } + + move_insert_iterator& operator*() { return *this; } + move_insert_iterator& operator++() { return *this; } + move_insert_iterator& operator++(int) { return *this; } +}; + +//! +//! <b>Returns</b>: move_insert_iterator<C>(x, it). +template <typename C> // C models Container +inline move_insert_iterator<C> move_inserter(C& x, typename C::iterator it) +{ + return move_insert_iterator<C>(x, it); +} + +} //namespace boost { + +#include <boost/move/detail/config_end.hpp> + +#endif //#ifndef BOOST_MOVE_ITERATOR_HPP diff --git a/boost/move/make_unique.hpp b/boost/move/make_unique.hpp new file mode 100644 index 0000000000..59cfafacb4 --- /dev/null +++ b/boost/move/make_unique.hpp @@ -0,0 +1,619 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2014. 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. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_MOVE_MAKE_UNIQUE_HPP_INCLUDED +#define BOOST_MOVE_MAKE_UNIQUE_HPP_INCLUDED + +#include <boost/move/detail/config_begin.hpp> +#include <boost/move/detail/workaround.hpp> +#include <boost/move/utility_core.hpp> +#include <boost/move/unique_ptr.hpp> +#include <cstddef> //for std::size_t +#include <boost/move/detail/unique_ptr_meta_utils.hpp> + +//!\file +//! Defines "make_unique" functions, which are factories to create instances +//! of unique_ptr depending on the passed arguments. +//! +//! This header can be a bit heavyweight in C++03 compilers due to the use of the +//! preprocessor library, that's why it's a a separate header from <tt>unique_ptr.hpp</tt> + +#if !defined(BOOST_MOVE_DOXYGEN_INVOKED) + +namespace std { //no namespace versioning in clang+libc++ + +struct nothrow_t; + +} //namespace std { + +namespace boost{ +namespace move_upmu { + +//Compile time switch between +//single element, unknown bound array +//and known bound array +template<class T> +struct unique_ptr_if +{ + typedef ::boost::movelib::unique_ptr<T> t_is_not_array; +}; + +template<class T> +struct unique_ptr_if<T[]> +{ + typedef ::boost::movelib::unique_ptr<T[]> t_is_array_of_unknown_bound; +}; + +template<class T, std::size_t N> +struct unique_ptr_if<T[N]> +{ + typedef void t_is_array_of_known_bound; +}; + +static std::nothrow_t *pnothrow; + +} //namespace move_upmu { +} //namespace boost{ + +#endif //!defined(BOOST_MOVE_DOXYGEN_INVOKED) + +namespace boost{ +namespace movelib { + +#if defined(BOOST_MOVE_DOXYGEN_INVOKED) || !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is not an array. +//! +//! <b>Returns</b>: <tt>unique_ptr<T>(new T(std::forward<Args>(args)...))</tt>. +template<class T, class... Args> +inline BOOST_MOVE_DOC1ST(unique_ptr<T>, + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array) + make_unique(BOOST_FWD_REF(Args)... args) +{ return unique_ptr<T>(new T(::boost::forward<Args>(args)...)); } + +//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is not an array. +//! +//! <b>Returns</b>: <tt>unique_ptr<T>(new T(std::nothrow)(std::forward<Args>(args)...))</tt>. +template<class T, class... Args> +inline BOOST_MOVE_DOC1ST(unique_ptr<T>, + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array) + make_unique_nothrow(BOOST_FWD_REF(Args)... args) +{ return unique_ptr<T>(new (*boost::move_upmu::pnothrow)T(::boost::forward<Args>(args)...)); } + +#else + + //0 arg + template<class T> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique() + { return unique_ptr<T>(new T()); } + + template<class T> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique_nothrow() + { return unique_ptr<T>(new (*boost::move_upmu::pnothrow)T()); } + + //1 arg + template<class T, class P0> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique( BOOST_FWD_REF(P0) p0 + ) + { + return unique_ptr<T> + ( new T( ::boost::forward<P0>(p0) + ) + ); + } + + template<class T, class P0> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique_nothrow( BOOST_FWD_REF(P0) p0 + ) + { + return unique_ptr<T> + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward<P0>(p0) + ) + ); + } + //2 arg + template<class T, class P0, class P1> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + ) + { + return unique_ptr<T> + ( new T( ::boost::forward<P0>(p0) + , ::boost::forward<P1>(p1) + ) + ); + } + + template<class T, class P0, class P1> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique_nothrow( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + ) + { + return unique_ptr<T> + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward<P0>(p0) + , ::boost::forward<P1>(p1) + ) + ); + } + //3 arg + template<class T, class P0, class P1, class P2> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + ) + { + return unique_ptr<T> + ( new T( ::boost::forward<P0>(p0) + , ::boost::forward<P1>(p1) + , ::boost::forward<P2>(p2) + ) + ); + } + + template<class T, class P0, class P1, class P2> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique_nothrow ( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + ) + { + return unique_ptr<T> + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward<P0>(p0) + , ::boost::forward<P1>(p1) + , ::boost::forward<P2>(p2) + ) + ); + } + //4 arg + template<class T, class P0, class P1, class P2, class P3> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + ) + { + return unique_ptr<T> + ( new T( ::boost::forward<P0>(p0) + , ::boost::forward<P1>(p1) + , ::boost::forward<P2>(p2) + , ::boost::forward<P3>(p3) + ) + ); + } + + template<class T, class P0, class P1, class P2, class P3> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique_nothrow ( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + ) + { + return unique_ptr<T> + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward<P0>(p0) + , ::boost::forward<P1>(p1) + , ::boost::forward<P2>(p2) + , ::boost::forward<P3>(p3) + ) + ); + } + //5 arg + template<class T, class P0, class P1, class P2, class P3, class P4> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + , BOOST_FWD_REF(P4) p4 + ) + { + return unique_ptr<T> + ( new T( ::boost::forward<P0>(p0) + , ::boost::forward<P1>(p1) + , ::boost::forward<P2>(p2) + , ::boost::forward<P3>(p3) + , ::boost::forward<P4>(p4) + ) + ); + } + + template<class T, class P0, class P1, class P2, class P3, class P4> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique_nothrow ( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + , BOOST_FWD_REF(P4) p4 + ) + { + return unique_ptr<T> + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward<P0>(p0) + , ::boost::forward<P1>(p1) + , ::boost::forward<P2>(p2) + , ::boost::forward<P3>(p3) + , ::boost::forward<P4>(p4) + ) + ); + } + //6 arg + template<class T, class P0, class P1, class P2, class P3, class P4, class P5> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + , BOOST_FWD_REF(P4) p4 + , BOOST_FWD_REF(P5) p5 + ) + { + return unique_ptr<T> + ( new T( ::boost::forward<P0>(p0) + , ::boost::forward<P1>(p1) + , ::boost::forward<P2>(p2) + , ::boost::forward<P3>(p3) + , ::boost::forward<P4>(p4) + , ::boost::forward<P5>(p5) + ) + ); + } + + template<class T, class P0, class P1, class P2, class P3, class P4, class P5> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique_nothrow ( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + , BOOST_FWD_REF(P4) p4 + , BOOST_FWD_REF(P5) p5 + ) + { + return unique_ptr<T> + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward<P0>(p0) + , ::boost::forward<P1>(p1) + , ::boost::forward<P2>(p2) + , ::boost::forward<P3>(p3) + , ::boost::forward<P4>(p4) + , ::boost::forward<P5>(p5) + ) + ); + } + //7 arg + template<class T, class P0, class P1, class P2, class P3, class P4, class P5, class P6> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + , BOOST_FWD_REF(P4) p4 + , BOOST_FWD_REF(P5) p5 + , BOOST_FWD_REF(P6) p6 + ) + { + return unique_ptr<T> + ( new T( ::boost::forward<P0>(p0) + , ::boost::forward<P1>(p1) + , ::boost::forward<P2>(p2) + , ::boost::forward<P3>(p3) + , ::boost::forward<P4>(p4) + , ::boost::forward<P5>(p5) + , ::boost::forward<P6>(p6) + ) + ); + } + + template<class T, class P0, class P1, class P2, class P3, class P4, class P5, class P6> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique_nothrow ( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + , BOOST_FWD_REF(P4) p4 + , BOOST_FWD_REF(P5) p5 + , BOOST_FWD_REF(P6) p6 + ) + { + return unique_ptr<T> + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward<P0>(p0) + , ::boost::forward<P1>(p1) + , ::boost::forward<P2>(p2) + , ::boost::forward<P3>(p3) + , ::boost::forward<P4>(p4) + , ::boost::forward<P5>(p5) + , ::boost::forward<P6>(p6) + ) + ); + } + + //8 arg + template<class T, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + , BOOST_FWD_REF(P4) p4 + , BOOST_FWD_REF(P5) p5 + , BOOST_FWD_REF(P6) p6 + , BOOST_FWD_REF(P7) p7 + ) + { + return unique_ptr<T> + ( new T( ::boost::forward<P0>(p0) + , ::boost::forward<P1>(p1) + , ::boost::forward<P2>(p2) + , ::boost::forward<P3>(p3) + , ::boost::forward<P4>(p4) + , ::boost::forward<P5>(p5) + , ::boost::forward<P6>(p6) + , ::boost::forward<P7>(p7) + ) + ); + } + + template<class T, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique_nothrow ( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + , BOOST_FWD_REF(P4) p4 + , BOOST_FWD_REF(P5) p5 + , BOOST_FWD_REF(P6) p6 + , BOOST_FWD_REF(P7) p7 + ) + { + return unique_ptr<T> + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward<P0>(p0) + , ::boost::forward<P1>(p1) + , ::boost::forward<P2>(p2) + , ::boost::forward<P3>(p3) + , ::boost::forward<P4>(p4) + , ::boost::forward<P5>(p5) + , ::boost::forward<P6>(p6) + , ::boost::forward<P7>(p7) + ) + ); + } + //9 arg + template<class T, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + , BOOST_FWD_REF(P4) p4 + , BOOST_FWD_REF(P5) p5 + , BOOST_FWD_REF(P6) p6 + , BOOST_FWD_REF(P7) p7 + , BOOST_FWD_REF(P8) p8 + ) + { + return unique_ptr<T> + ( new T( ::boost::forward<P0>(p0) + , ::boost::forward<P1>(p1) + , ::boost::forward<P2>(p2) + , ::boost::forward<P3>(p3) + , ::boost::forward<P4>(p4) + , ::boost::forward<P5>(p5) + , ::boost::forward<P6>(p6) + , ::boost::forward<P7>(p7) + , ::boost::forward<P8>(p8) + ) + ); + } + + template<class T, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique_nothrow ( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + , BOOST_FWD_REF(P4) p4 + , BOOST_FWD_REF(P5) p5 + , BOOST_FWD_REF(P6) p6 + , BOOST_FWD_REF(P7) p7 + , BOOST_FWD_REF(P8) p8 + ) + { + return unique_ptr<T> + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward<P0>(p0) + , ::boost::forward<P1>(p1) + , ::boost::forward<P2>(p2) + , ::boost::forward<P3>(p3) + , ::boost::forward<P4>(p4) + , ::boost::forward<P5>(p5) + , ::boost::forward<P6>(p6) + , ::boost::forward<P7>(p7) + , ::boost::forward<P8>(p8) + ) + ); + } + //10 arg + template<class T, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + , BOOST_FWD_REF(P4) p4 + , BOOST_FWD_REF(P5) p5 + , BOOST_FWD_REF(P6) p6 + , BOOST_FWD_REF(P7) p7 + , BOOST_FWD_REF(P8) p8 + , BOOST_FWD_REF(P9) p9 + ) + { + return unique_ptr<T> + ( new T( ::boost::forward<P0>(p0) + , ::boost::forward<P1>(p1) + , ::boost::forward<P2>(p2) + , ::boost::forward<P3>(p3) + , ::boost::forward<P4>(p4) + , ::boost::forward<P5>(p5) + , ::boost::forward<P6>(p6) + , ::boost::forward<P7>(p7) + , ::boost::forward<P8>(p8) + , ::boost::forward<P9>(p9) + ) + ); + } + + template<class T, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9> + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array + make_unique_nothrow ( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + , BOOST_FWD_REF(P4) p4 + , BOOST_FWD_REF(P5) p5 + , BOOST_FWD_REF(P6) p6 + , BOOST_FWD_REF(P7) p7 + , BOOST_FWD_REF(P8) p8 + , BOOST_FWD_REF(P9) p9 + ) + { + return unique_ptr<T> + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward<P0>(p0) + , ::boost::forward<P1>(p1) + , ::boost::forward<P2>(p2) + , ::boost::forward<P3>(p3) + , ::boost::forward<P4>(p4) + , ::boost::forward<P5>(p5) + , ::boost::forward<P6>(p6) + , ::boost::forward<P7>(p7) + , ::boost::forward<P8>(p8) + , ::boost::forward<P9>(p9) + ) + ); + } + +#endif + +//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is not an array. +//! +//! <b>Returns</b>: <tt>unique_ptr<T>(new T)</tt> (default initialization) +template<class T> +inline BOOST_MOVE_DOC1ST(unique_ptr<T>, + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array) + make_unique_definit() +{ + return unique_ptr<T>(new T); +} + +//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is not an array. +//! +//! <b>Returns</b>: <tt>unique_ptr<T>(new T(std::nothrow)</tt> (default initialization) +template<class T> +inline BOOST_MOVE_DOC1ST(unique_ptr<T>, + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array) + make_unique_nothrow_definit() +{ + return unique_ptr<T>(new (*boost::move_upmu::pnothrow)T); +} + +//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is an array of +//! unknown bound. +//! +//! <b>Returns</b>: <tt>unique_ptr<T>(new remove_extent_t<T>[n]())</tt> (value initialization) +template<class T> +inline BOOST_MOVE_DOC1ST(unique_ptr<T>, + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_unknown_bound) + make_unique(std::size_t n) +{ + typedef typename ::boost::move_upmu::remove_extent<T>::type U; + return unique_ptr<T>(new U[n]()); +} + +//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is an array of +//! unknown bound. +//! +//! <b>Returns</b>: <tt>unique_ptr<T>(new (std::nothrow)remove_extent_t<T>[n]())</tt> (value initialization) +template<class T> +inline BOOST_MOVE_DOC1ST(unique_ptr<T>, + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_unknown_bound) + make_unique_nothrow(std::size_t n) +{ + typedef typename ::boost::move_upmu::remove_extent<T>::type U; + return unique_ptr<T>(new (*boost::move_upmu::pnothrow)U[n]()); +} + +//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is an array of +//! unknown bound. +//! +//! <b>Returns</b>: <tt>unique_ptr<T>(new remove_extent_t<T>[n])</tt> (default initialization) +template<class T> +inline BOOST_MOVE_DOC1ST(unique_ptr<T>, + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_unknown_bound) + make_unique_definit(std::size_t n) +{ + typedef typename ::boost::move_upmu::remove_extent<T>::type U; + return unique_ptr<T>(new U[n]); +} + +//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is an array of +//! unknown bound. +//! +//! <b>Returns</b>: <tt>unique_ptr<T>(new (std::nothrow)remove_extent_t<T>[n])</tt> (default initialization) +template<class T> +inline BOOST_MOVE_DOC1ST(unique_ptr<T>, + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_unknown_bound) + make_unique_nothrow_definit(std::size_t n) +{ + typedef typename ::boost::move_upmu::remove_extent<T>::type U; + return unique_ptr<T>(new (*boost::move_upmu::pnothrow) U[n]); +} + +#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) + +//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is +//! an array of known bound. +template<class T, class... Args> +inline BOOST_MOVE_DOC1ST(unspecified, + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_known_bound) + make_unique(BOOST_FWD_REF(Args) ...) = delete; + +//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is +//! an array of known bound. +template<class T, class... Args> +inline BOOST_MOVE_DOC1ST(unspecified, + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_known_bound) + make_unique_definit(BOOST_FWD_REF(Args) ...) = delete; + +//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is +//! an array of known bound. +template<class T, class... Args> +inline BOOST_MOVE_DOC1ST(unspecified, + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_known_bound) + make_unique_nothrow(BOOST_FWD_REF(Args) ...) = delete; + +//! <b>Remarks</b>: This function shall not participate in overload resolution unless T is +//! an array of known bound. +template<class T, class... Args> +inline BOOST_MOVE_DOC1ST(unspecified, + typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_known_bound) + make_unique_nothrow_definit(BOOST_FWD_REF(Args) ...) = delete; + +#endif + +} //namespace movelib { + +} //namespace boost{ + +#include <boost/move/detail/config_end.hpp> + +#endif //#ifndef BOOST_MOVE_MAKE_UNIQUE_HPP_INCLUDED diff --git a/boost/move/move.hpp b/boost/move/move.hpp index 6029d6d578..5a22d316fc 100644 --- a/boost/move/move.hpp +++ b/boost/move/move.hpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////////////////////// // // (C) Copyright David Abrahams, Vicente Botet 2009. -// (C) Copyright Ion Gaztanaga 2009-2010. +// (C) Copyright Ion Gaztanaga 2009-2012. // 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) @@ -11,1263 +11,17 @@ ////////////////////////////////////////////////////////////////////////////// //! \file +//! A general library header that includes +//! the rest of top-level headers. #ifndef BOOST_MOVE_MOVE_HPP #define BOOST_MOVE_MOVE_HPP -#if !defined(BOOST_MOVE_DOXYGEN_INVOKED) - -/// @cond - -#include <boost/config.hpp> - -#ifdef BOOST_MSVC - #ifndef _CRT_SECURE_NO_DEPRECATE - #define BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE - #define _CRT_SECURE_NO_DEPRECATE - #endif - #ifndef _SCL_SECURE_NO_WARNINGS - #define BOOST_INTERPROCESS_SCL_SECURE_NO_WARNINGS - #define _SCL_SECURE_NO_WARNINGS - #endif - #pragma warning (push) - #pragma warning(disable:4996) -#endif - -#include <algorithm> //copy, copy_backward -#include <memory> //uninitialized_copy -#include <iterator> //std::iterator - -#define BOOST_MOVE_AVOID_BOOST_DEPENDENCIES - -//If boost dependencies are avoided include all machinery -#if !defined(BOOST_MOVE_AVOID_BOOST_DEPENDENCIES) - #include <boost/utility/enable_if.hpp> - #include <boost/utility/addressof.hpp> - #include <boost/mpl/if.hpp> - #include <boost/mpl/bool.hpp> - #include <boost/mpl/and.hpp> - #include <boost/mpl/not.hpp> - #include <boost/mpl/identity.hpp> - #include <boost/type_traits/is_class.hpp> - #include <boost/type_traits/is_convertible.hpp> - #include <boost/type_traits/has_trivial_destructor.hpp> - #include <boost/type_traits/integral_constant.hpp> - - #define BOOST_MOVE_MPL_NS ::boost::mpl - #define BOOST_MOVE_BOOST_NS ::boost -#else - #define BOOST_MOVE_MPL_NS ::boost::move_detail - #define BOOST_MOVE_BOOST_NS ::boost::move_detail -#endif //#ifdef BOOST_MOVE_AVOID_BOOST_DEPENDENCIES - -//Small meta-typetraits to support move -#ifdef BOOST_MOVE_AVOID_BOOST_DEPENDENCIES - - namespace boost { - namespace move_detail { - - //if_ - template<bool C, typename T1, typename T2> - struct if_c - { - typedef T1 type; - }; - - template<typename T1, typename T2> - struct if_c<false,T1,T2> - { - typedef T2 type; - }; - - template<typename T1, typename T2, typename T3> - struct if_ - { - typedef typename if_c<0 != T1::value, T2, T3>::type type; - }; - - //enable_if_ - template <bool B, class T = void> - struct enable_if_c - { - typedef T type; - }; - - template <class T> - struct enable_if_c<false, T> {}; - - template <class Cond, class T = void> - struct enable_if : public enable_if_c<Cond::value, T> {}; - - template <class Cond, class T = void> - struct disable_if : public enable_if_c<!Cond::value, T> {}; - - //integral_constant - template<class T, T v> - struct integral_constant - { - static const T value = v; - typedef T value_type; - typedef integral_constant<T, v> type; - }; - - //identity - template <class T> - struct identity - { - typedef T type; - }; - - //is_convertible - template <class T, class U> - class is_convertible - { - typedef char true_t; - class false_t { char dummy[2]; }; - static true_t dispatch(U); - static false_t dispatch(...); - static T &trigger(); - public: - enum { value = sizeof(dispatch(trigger())) == sizeof(true_t) }; - }; - - //and_ not_ - template <typename Condition1, typename Condition2, typename Condition3 = integral_constant<bool, true> > - struct and_ - : public integral_constant<bool, Condition1::value && Condition2::value && Condition3::value> - {}; - - template <typename Boolean> - struct not_ - : public integral_constant<bool, !Boolean::value> - {}; - - //is_lvalue_reference - template<class T> - struct is_lvalue_reference - : public integral_constant<bool, false> - {}; - - template<class T> - struct is_lvalue_reference<T&> - : public integral_constant<bool, true> - {}; - - //has_trivial_destructor - template<class T> - struct has_trivial_destructor - : public integral_constant<bool, false> - {}; - - //addressof - template<class T> struct addr_impl_ref - { - T & v_; - inline addr_impl_ref( T & v ): v_( v ) {} - inline operator T& () const { return v_; } - - private: - addr_impl_ref & operator=(const addr_impl_ref &); - }; - - template<class T> struct addressof_impl - { - static inline T * f( T & v, long ) - { - return reinterpret_cast<T*>( - &const_cast<char&>(reinterpret_cast<const volatile char &>(v))); - } - - static inline T * f( T * v, int ) - { return v; } - }; - - template<class T> - inline T * addressof( T & v ) - { - return ::boost::move_detail::addressof_impl<T>::f - ( ::boost::move_detail::addr_impl_ref<T>( v ), 0 ); - } - - } //namespace move_detail { - } //namespace boost { - -#endif //BOOST_MOVE_AVOID_BOOST_DEPENDENCIES - -//Compiler workaround detection -#if !defined(BOOST_NO_RVALUE_REFERENCES) - - #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 5) && !defined(__clang__) - //Pre-standard rvalue binding rules - #define BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES - #elif defined(_MSC_VER) && (_MSC_VER == 1600) - //Standard rvalue binding rules but with some bugs - #define BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG - //Use standard library for MSVC to avoid namespace issues as - //some move calls in the STL are not fully qualified. - //#define BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE - #endif - -#endif - -/// @endcond - -#endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED) - -#if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED) - - //Move emulation rv breaks standard aliasing rules so add workarounds for some compilers - #if defined(__GNUC__) && (__GNUC__ >= 4) - #define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS __attribute__((__may_alias__)) - #else - #define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS - #endif - - namespace boost { - - namespace move_detail { - template<class T> - struct is_class_or_union - { - struct twochar { char _[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); - }; - struct empty{}; - } - - ////////////////////////////////////////////////////////////////////////////// - // - // struct rv - // - ////////////////////////////////////////////////////////////////////////////// - template <class T> - class rv - : public BOOST_MOVE_MPL_NS::if_c - < ::boost::move_detail::is_class_or_union<T>::value - , T - , ::boost::move_detail::empty - >::type - { - rv(); - ~rv(); - rv(rv const&); - void operator=(rv const&); - } BOOST_MOVE_ATTRIBUTE_MAY_ALIAS; - - - - ////////////////////////////////////////////////////////////////////////////// - // - // move_detail::is_rv - // - ////////////////////////////////////////////////////////////////////////////// - - namespace move_detail { - - template <class T> - struct is_rv - : BOOST_MOVE_BOOST_NS::integral_constant<bool, false> - {}; - - template <class T> - struct is_rv< rv<T> > - : BOOST_MOVE_BOOST_NS::integral_constant<bool, true> - {}; - - template <class T> - struct is_rv< const rv<T> > - : BOOST_MOVE_BOOST_NS::integral_constant<bool, true> - {}; - - } //namespace move_detail { - - ////////////////////////////////////////////////////////////////////////////// - // - // has_move_emulation_enabled - // - ////////////////////////////////////////////////////////////////////////////// - template<class T> - struct has_move_emulation_enabled - : BOOST_MOVE_BOOST_NS::is_convertible< T, ::boost::rv<T>& > - {}; - - template<class T> - struct has_move_emulation_enabled<T&> - : BOOST_MOVE_BOOST_NS::integral_constant<bool, false> - {}; - - template<class T> - struct has_move_emulation_enabled< ::boost::rv<T> > - : BOOST_MOVE_BOOST_NS::integral_constant<bool, false> - {}; - - template <class T> - struct has_move_emulation_enabled_aux - : has_move_emulation_enabled<T> {}; - - template <class T> - struct has_nothrow_move - : public BOOST_MOVE_BOOST_NS::integral_constant<bool, false> - {}; - - ////////////////////////////////////////////////////////////////////////////// - // - // move() - // - ////////////////////////////////////////////////////////////////////////////// - - template <class T> - inline typename BOOST_MOVE_BOOST_NS::disable_if<has_move_emulation_enabled_aux<T>, T&>::type move(T& x) - { - return x; - } - - template <class T> - inline typename BOOST_MOVE_BOOST_NS::enable_if<has_move_emulation_enabled<T>, rv<T>&>::type move(T& x) - { - return *static_cast<rv<T>* >(BOOST_MOVE_BOOST_NS::addressof(x)); - } - - template <class T> - inline typename BOOST_MOVE_BOOST_NS::enable_if<has_move_emulation_enabled<T>, rv<T>&>::type move(rv<T>& x) - { - return x; - } - - #define BOOST_RV_REF(TYPE)\ - ::boost::rv< TYPE >& \ - // - - #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ - ::boost::rv< TYPE<ARG1, ARG2> >& \ - // - - #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ - ::boost::rv< TYPE<ARG1, ARG2, ARG3> >& \ - // - - #define BOOST_RV_REF_BEG\ - ::boost::rv< \ - // - - #define BOOST_RV_REF_END\ - >& \ - // - - - - #define BOOST_FWD_REF(TYPE)\ - const TYPE & \ - // - - #define BOOST_CATCH_CONST_RLVALUE(TYPE)\ - const ::boost::rv< TYPE >& \ - // - - #define BOOST_COPY_ASSIGN_REF(TYPE)\ - const ::boost::rv< TYPE >& \ - // - - #define BOOST_COPY_ASSIGN_REF_BEG \ - const ::boost::rv< \ - // - - #define BOOST_COPY_ASSIGN_REF_END \ - >& \ - // - - #define BOOST_MOVE_COPY_ASSIGN_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ - const ::boost::rv< TYPE<ARG1, ARG2> >& \ - // - - #define BOOST_MOVE_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ - const ::boost::rv< TYPE<ARG1, ARG2, ARG3> >& \ - // - - ////////////////////////////////////////////////////////////////////////////// - // - // forward() - // - ////////////////////////////////////////////////////////////////////////////// - - template <class T> - inline typename BOOST_MOVE_BOOST_NS::enable_if< ::boost::move_detail::is_rv<T>, T &>::type - forward(const typename BOOST_MOVE_MPL_NS::identity<T>::type &x) - { - return const_cast<T&>(x); - } - - template <class T> - inline typename BOOST_MOVE_BOOST_NS::disable_if< ::boost::move_detail::is_rv<T>, const T &>::type - forward(const typename BOOST_MOVE_MPL_NS::identity<T>::type &x) - { - return x; - } - - ////////////////////////////////////////////////////////////////////////////// - // - // BOOST_MOVABLE_BUT_NOT_COPYABLE - // - ////////////////////////////////////////////////////////////////////////////// - #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\ - private:\ - TYPE(TYPE &);\ - TYPE& operator=(TYPE &);\ - public:\ - operator ::boost::rv<TYPE>&() \ - { return *static_cast< ::boost::rv<TYPE>* >(this); }\ - operator const ::boost::rv<TYPE>&() const \ - { return *static_cast<const ::boost::rv<TYPE>* >(this); }\ - private:\ - // - - ////////////////////////////////////////////////////////////////////////////// - // - // BOOST_COPYABLE_AND_MOVABLE - // - ////////////////////////////////////////////////////////////////////////////// - - #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\ - public:\ - TYPE& operator=(TYPE &t)\ - { this->operator=(static_cast<const ::boost::rv<TYPE> &>(const_cast<const TYPE &>(t))); return *this;}\ - public:\ - operator ::boost::rv<TYPE>&() \ - { return *static_cast< ::boost::rv<TYPE>* >(this); }\ - operator const ::boost::rv<TYPE>&() const \ - { return *static_cast<const ::boost::rv<TYPE>* >(this); }\ - private:\ - // - - #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\ - public:\ - operator ::boost::rv<TYPE>&() \ - { return *static_cast< ::boost::rv<TYPE>* >(this); }\ - operator const ::boost::rv<TYPE>&() const \ - { return *static_cast<const ::boost::rv<TYPE>* >(this); }\ - private:\ - // - - } //namespace boost - -#else //BOOST_NO_RVALUE_REFERENCES - - namespace boost{ - - //! By default this traits returns false. Classes with non-throwing move constructor - //! and assignment should specialize this trait to obtain some performance improvements. - template <class T> - struct has_nothrow_move - : public BOOST_MOVE_MPL_NS::integral_constant<bool, false> - {}; - - } // namespace boost{ - - #if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE) - #include <utility> - - namespace boost{ - - using ::std::move; - using ::std::forward; - using ::std::move_backward; - - } //namespace boost - - #else //!BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE - - #include <boost/type_traits/remove_reference.hpp> - - namespace boost { - - ////////////////////////////////////////////////////////////////////////////// - // - // move - // - ////////////////////////////////////////////////////////////////////////////// - - #if defined(BOOST_MOVE_DOXYGEN_INVOKED) - //! This function provides a way to convert a reference into a rvalue reference - //! in compilers with rvalue references. For other compilers converts T & into - //! <i>::boost::rv<T> &</i> so that move emulation is activated. - template <class T> - rvalue_reference move (input_reference); - - #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) - - //Old move approach, lvalues could bind to rvalue references - template <class T> - inline typename remove_reference<T>::type && move(T&& t) - { return t; } - - #else //Old move - - template <class T> - inline typename remove_reference<T>::type && move(T&& t) - { return static_cast<typename remove_reference<T>::type &&>(t); } - - #endif //Old move - - ////////////////////////////////////////////////////////////////////////////// - // - // forward - // - ////////////////////////////////////////////////////////////////////////////// - - - #if defined(BOOST_MOVE_DOXYGEN_INVOKED) - //! This function provides limited form of forwarding that is usually enough for - //! in-place construction and avoids the exponential overloading necessary for - //! perfect forwarding in C++03. - //! - //! For compilers with rvalue references this function provides perfect forwarding. - //! - //! Otherwise: - //! * If input_reference binds to const ::boost::rv<T> & then it output_reference is - //! ::boost::rev<T> & - //! - //! * Else, input_reference is equal to output_reference is equal to input_reference. - template <class T> output_reference forward(input_reference); - #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) - - //Old move approach, lvalues could bind to rvalue references - - template <class T> - inline T&& forward (typename BOOST_MOVE_MPL_NS::identity<T>::type&& t) - { return t; } - - #else //Old move - - //Implementation #5 from N2951, thanks to Howard Hinnant - - template <class T, class U> - inline T&& forward(U&& t - , typename BOOST_MOVE_BOOST_NS::enable_if_c< - move_detail::is_lvalue_reference<T>::value ? move_detail::is_lvalue_reference<U>::value : true>::type * = 0/* - , typename BOOST_MOVE_BOOST_NS::enable_if_c< - move_detail::is_convertible - <typename remove_reference<U>::type*, typename remove_reference<T>::type*>::value>::type * = 0*/) - { return static_cast<T&&>(t); } - - #endif //BOOST_MOVE_DOXYGEN_INVOKED - - } //namespace boost { - - #endif //#if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE) - - //! This macro marks a type as movable but not copyable, disabling copy construction - //! and assignment. The user will need to write a move constructor/assignment as explained - //! in the documentation to fully write a movable but not copyable class. - #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\ - public:\ - typedef int boost_move_emulation_t;\ - private:\ - TYPE(const TYPE &);\ - TYPE& operator=(const TYPE &);\ - // - - //! This macro marks a type as copyable and movable. - //! The user will need to write a move constructor/assignment and a copy assignment - //! as explained in the documentation to fully write a copyable and movable class. - #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\ - // - - #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\ - // - - //!This macro is used to achieve portable syntax in move - //!constructors and assignments for classes marked as - //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE - #define BOOST_RV_REF(TYPE)\ - TYPE && \ - // - - //!This macro is used to achieve portable syntax in move - //!constructors and assignments for template classes marked as - //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE. - //!As macros have problem with comma-separatd template arguments, - //!the template argument must be preceded with BOOST_RV_REF_START - //!and ended with BOOST_RV_REF_END - #define BOOST_RV_REF_BEG\ - \ - // - - //!This macro is used to achieve portable syntax in move - //!constructors and assignments for template classes marked as - //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE. - //!As macros have problem with comma-separatd template arguments, - //!the template argument must be preceded with BOOST_RV_REF_START - //!and ended with BOOST_RV_REF_END - #define BOOST_RV_REF_END\ - && \ - - //!This macro is used to achieve portable syntax in copy - //!assignment for classes marked as BOOST_COPYABLE_AND_MOVABLE. - #define BOOST_COPY_ASSIGN_REF(TYPE)\ - const TYPE & \ - // - - //! This macro is used to implement portable perfect forwarding - //! as explained in the documentation. - #define BOOST_FWD_REF(TYPE)\ - TYPE && \ - // - - - #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) - /// @cond - - #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ - TYPE<ARG1, ARG2> && \ - // - - #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ - TYPE<ARG1, ARG2, ARG3> && \ - // - - #define BOOST_COPY_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ - const TYPE<ARG1, ARG2> & \ - // - - #define BOOST_COPY_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ - TYPE<ARG1, ARG2, ARG3>& \ - // - - #define BOOST_CATCH_CONST_RLVALUE(TYPE)\ - const TYPE & \ - // - - /// @endcond - - #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED) - -#endif //BOOST_NO_RVALUE_REFERENCES - -namespace boost { - -////////////////////////////////////////////////////////////////////////////// -// -// move_iterator -// -////////////////////////////////////////////////////////////////////////////// - -//! Class template move_iterator is an iterator adaptor with the same behavior -//! as the underlying iterator except that its dereference operator implicitly -//! converts the value returned by the underlying iterator's dereference operator -//! to an rvalue reference. Some generic algorithms can be called with move -//! iterators to replace copying with moving. -template <class It> -class move_iterator -{ - public: - typedef It iterator_type; - typedef typename std::iterator_traits<iterator_type>::value_type value_type; - #if !defined(BOOST_NO_RVALUE_REFERENCES) || defined(BOOST_MOVE_DOXYGEN_INVOKED) - typedef value_type && reference; - #else - typedef typename BOOST_MOVE_MPL_NS::if_ - < ::boost::has_move_emulation_enabled<value_type> - , ::boost::rv<value_type>& - , value_type & >::type reference; - #endif - typedef It pointer; - typedef typename std::iterator_traits<iterator_type>::difference_type difference_type; - typedef typename std::iterator_traits<iterator_type>::iterator_category iterator_category; - - move_iterator() - {} - - explicit move_iterator(It i) - : m_it(i) - {} - - template <class U> - move_iterator(const move_iterator<U>& u) - : m_it(u.base()) - {} - - iterator_type base() const - { return m_it; } - - reference operator*() const - { - #if defined(BOOST_NO_RVALUE_REFERENCES) || defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) - return *m_it; - #else - return ::boost::move(*m_it); - #endif - } - - pointer operator->() const - { return m_it; } - - move_iterator& operator++() - { ++m_it; return *this; } - - move_iterator<iterator_type> operator++(int) - { move_iterator<iterator_type> tmp(*this); ++(*this); return tmp; } - - move_iterator& operator--() - { --m_it; return *this; } - - move_iterator<iterator_type> operator--(int) - { move_iterator<iterator_type> tmp(*this); --(*this); return tmp; } - - move_iterator<iterator_type> operator+ (difference_type n) const - { return move_iterator<iterator_type>(m_it + n); } - - move_iterator& operator+=(difference_type n) - { m_it += n; return *this; } - - move_iterator<iterator_type> operator- (difference_type n) const - { return move_iterator<iterator_type>(m_it - n); } - - move_iterator& operator-=(difference_type n) - { m_it -= n; return *this; } - - reference operator[](difference_type n) const - { - #if defined(BOOST_NO_RVALUE_REFERENCES) || defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) - return m_it[n]; - #else - return ::boost::move(m_it[n]); - #endif - } - - friend bool operator==(const move_iterator& x, const move_iterator& y) - { return x.base() == y.base(); } - - friend bool operator!=(const move_iterator& x, const move_iterator& y) - { return x.base() != y.base(); } - - friend bool operator< (const move_iterator& x, const move_iterator& y) - { return x.base() < y.base(); } - - friend bool operator<=(const move_iterator& x, const move_iterator& y) - { return x.base() <= y.base(); } - - friend bool operator> (const move_iterator& x, const move_iterator& y) - { return x.base() > y.base(); } - - friend bool operator>=(const move_iterator& x, const move_iterator& y) - { return x.base() >= y.base(); } - - friend difference_type operator-(const move_iterator& x, const move_iterator& y) - { return x.base() - y.base(); } - - friend move_iterator operator+(difference_type n, const move_iterator& x) - { return move_iterator(x.base() + n); } - - private: - It m_it; -}; - - -//is_move_iterator -namespace move_detail { - -template <class I> -struct is_move_iterator - : public BOOST_MOVE_BOOST_NS::integral_constant<bool, false> -{ -}; - -template <class I> -struct is_move_iterator< ::boost::move_iterator<I> > - : public BOOST_MOVE_BOOST_NS::integral_constant<bool, true> -{ -}; - -} //namespace move_detail { - -////////////////////////////////////////////////////////////////////////////// -// -// move_iterator -// -////////////////////////////////////////////////////////////////////////////// - -//! -//! <b>Returns</b>: move_iterator<It>(i). -template<class It> -inline move_iterator<It> make_move_iterator(const It &it) -{ return move_iterator<It>(it); } - -////////////////////////////////////////////////////////////////////////////// -// -// back_move_insert_iterator -// -////////////////////////////////////////////////////////////////////////////// - - -//! A move insert iterator that move constructs elements at the -//! back of a container -template <typename C> // C models Container -class back_move_insert_iterator - : public std::iterator<std::output_iterator_tag, void, void, void, void> -{ - C* container_m; - - public: - typedef C container_type; - typedef typename C::value_type value_type; - typedef typename C::reference reference; - - explicit back_move_insert_iterator(C& x) : container_m(&x) { } - - back_move_insert_iterator& operator=(reference x) - { container_m->push_back(boost::move(x)); return *this; } - - back_move_insert_iterator& operator=(BOOST_RV_REF(value_type) x) - { reference rx = x; return this->operator=(rx); } - - back_move_insert_iterator& operator*() { return *this; } - back_move_insert_iterator& operator++() { return *this; } - back_move_insert_iterator& operator++(int) { return *this; } -}; - -//! -//! <b>Returns</b>: back_move_insert_iterator<C>(x). -template <typename C> // C models Container -inline back_move_insert_iterator<C> back_move_inserter(C& x) -{ - return back_move_insert_iterator<C>(x); -} - -////////////////////////////////////////////////////////////////////////////// -// -// front_move_insert_iterator -// -////////////////////////////////////////////////////////////////////////////// - -//! A move insert iterator that move constructs elements int the -//! front of a container -template <typename C> // C models Container -class front_move_insert_iterator - : public std::iterator<std::output_iterator_tag, void, void, void, void> -{ - C* container_m; - -public: - typedef C container_type; - typedef typename C::value_type value_type; - typedef typename C::reference reference; - - explicit front_move_insert_iterator(C& x) : container_m(&x) { } - - front_move_insert_iterator& operator=(reference x) - { container_m->push_front(boost::move(x)); return *this; } - - front_move_insert_iterator& operator=(BOOST_RV_REF(value_type) x) - { reference rx = x; return this->operator=(rx); } - - front_move_insert_iterator& operator*() { return *this; } - front_move_insert_iterator& operator++() { return *this; } - front_move_insert_iterator& operator++(int) { return *this; } -}; - -//! -//! <b>Returns</b>: front_move_insert_iterator<C>(x). -template <typename C> // C models Container -inline front_move_insert_iterator<C> front_move_inserter(C& x) -{ - return front_move_insert_iterator<C>(x); -} - -////////////////////////////////////////////////////////////////////////////// -// -// insert_move_iterator -// -////////////////////////////////////////////////////////////////////////////// -template <typename C> // C models Container -class move_insert_iterator - : public std::iterator<std::output_iterator_tag, void, void, void, void> -{ - C* container_m; - typename C::iterator pos_; - - public: - typedef C container_type; - typedef typename C::value_type value_type; - typedef typename C::reference reference; - - explicit move_insert_iterator(C& x, typename C::iterator pos) - : container_m(&x), pos_(pos) - {} - - move_insert_iterator& operator=(reference x) - { - pos_ = container_m->insert(pos_, ::boost::move(x)); - ++pos_; - return *this; - } - - move_insert_iterator& operator=(BOOST_RV_REF(value_type) x) - { reference rx = x; return this->operator=(rx); } - - move_insert_iterator& operator*() { return *this; } - move_insert_iterator& operator++() { return *this; } - move_insert_iterator& operator++(int) { return *this; } -}; - -//! -//! <b>Returns</b>: move_insert_iterator<C>(x, it). -template <typename C> // C models Container -inline move_insert_iterator<C> move_inserter(C& x, typename C::iterator it) -{ - return move_insert_iterator<C>(x, it); -} - -////////////////////////////////////////////////////////////////////////////// -// -// move -// -////////////////////////////////////////////////////////////////////////////// - -#if !defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE) - - //! <b>Effects</b>: Moves elements in the range [first,last) into the range [result,result + (last - - //! first)) starting from first and proceeding to last. For each non-negative integer n < (last-first), - //! performs *(result + n) = ::boost::move (*(first + n)). - //! - //! <b>Effects</b>: result + (last - first). - //! - //! <b>Requires</b>: result shall not be in the range [first,last). - //! - //! <b>Complexity</b>: Exactly last - first move assignments. - template <typename I, // I models InputIterator - typename O> // O models OutputIterator - O move(I f, I l, O result) - { - while (f != l) { - *result = ::boost::move(*f); - ++f; ++result; - } - return result; - } - - ////////////////////////////////////////////////////////////////////////////// - // - // move_backward - // - ////////////////////////////////////////////////////////////////////////////// - - //! <b>Effects</b>: Moves elements in the range [first,last) into the range - //! [result - (last-first),result) starting from last - 1 and proceeding to - //! first. For each positive integer n <= (last - first), - //! performs *(result - n) = ::boost::move(*(last - n)). - //! - //! <b>Requires</b>: result shall not be in the range [first,last). - //! - //! <b>Returns</b>: result - (last - first). - //! - //! <b>Complexity</b>: Exactly last - first assignments. - template <typename I, // I models BidirectionalIterator - typename O> // O models BidirectionalIterator - O move_backward(I f, I l, O result) - { - while (f != l) { - --l; --result; - *result = ::boost::move(*l); - } - return result; - } - -#endif //!defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE) - -////////////////////////////////////////////////////////////////////////////// -// -// uninitialized_move -// -////////////////////////////////////////////////////////////////////////////// - -//! <b>Effects</b>: -//! \code -//! for (; first != last; ++result, ++first) -//! new (static_cast<void*>(&*result)) -//! typename iterator_traits<ForwardIterator>::value_type(boost::move(*first)); -//! \endcode -//! -//! <b>Returns</b>: result -template - <typename I, // I models InputIterator - typename F> // F models ForwardIterator -F uninitialized_move(I f, I l, F r - /// @cond -// ,typename BOOST_MOVE_BOOST_NS::enable_if<has_move_emulation_enabled<typename std::iterator_traits<I>::value_type> >::type* = 0 - /// @endcond - ) -{ - typedef typename std::iterator_traits<I>::value_type input_value_type; - while (f != l) { - ::new(static_cast<void*>(&*r)) input_value_type(boost::move(*f)); - ++f; ++r; - } - return r; -} - -/// @cond -/* -template - <typename I, // I models InputIterator - typename F> // F models ForwardIterator -F uninitialized_move(I f, I l, F r, - typename BOOST_MOVE_BOOST_NS::disable_if<has_move_emulation_enabled<typename std::iterator_traits<I>::value_type> >::type* = 0) -{ - return std::uninitialized_copy(f, l, r); -} -*/ - -////////////////////////////////////////////////////////////////////////////// -// -// uninitialized_copy_or_move -// -////////////////////////////////////////////////////////////////////////////// - -namespace move_detail { - -template -<typename I, // I models InputIterator -typename F> // F models ForwardIterator -inline F uninitialized_move_move_iterator(I f, I l, F r -// ,typename BOOST_MOVE_BOOST_NS::enable_if< has_move_emulation_enabled<typename I::value_type> >::type* = 0 -) -{ - return ::boost::uninitialized_move(f, l, r); -} -/* -template -<typename I, // I models InputIterator -typename F> // F models ForwardIterator -F uninitialized_move_move_iterator(I f, I l, F r, - typename BOOST_MOVE_BOOST_NS::disable_if< has_move_emulation_enabled<typename I::value_type> >::type* = 0) -{ - return std::uninitialized_copy(f.base(), l.base(), r); -} -*/ -} //namespace move_detail { - -template -<typename I, // I models InputIterator -typename F> // F models ForwardIterator -inline F uninitialized_copy_or_move(I f, I l, F r, - typename BOOST_MOVE_BOOST_NS::enable_if< move_detail::is_move_iterator<I> >::type* = 0) -{ - return ::boost::move_detail::uninitialized_move_move_iterator(f, l, r); -} - -////////////////////////////////////////////////////////////////////////////// -// -// copy_or_move -// -////////////////////////////////////////////////////////////////////////////// - -namespace move_detail { - -template -<typename I, // I models InputIterator -typename F> // F models ForwardIterator -inline F move_move_iterator(I f, I l, F r -// ,typename BOOST_MOVE_BOOST_NS::enable_if< has_move_emulation_enabled<typename I::value_type> >::type* = 0 -) -{ - return ::boost::move(f, l, r); -} -/* -template -<typename I, // I models InputIterator -typename F> // F models ForwardIterator -F move_move_iterator(I f, I l, F r, - typename BOOST_MOVE_BOOST_NS::disable_if< has_move_emulation_enabled<typename I::value_type> >::type* = 0) -{ - return std::copy(f.base(), l.base(), r); -} -*/ - -} //namespace move_detail { - -template -<typename I, // I models InputIterator -typename F> // F models ForwardIterator -inline F copy_or_move(I f, I l, F r, - typename BOOST_MOVE_BOOST_NS::enable_if< move_detail::is_move_iterator<I> >::type* = 0) -{ - return ::boost::move_detail::move_move_iterator(f, l, r); -} - -/// @endcond - -//! <b>Effects</b>: -//! \code -//! for (; first != last; ++result, ++first) -//! new (static_cast<void*>(&*result)) -//! typename iterator_traits<ForwardIterator>::value_type(*first); -//! \endcode -//! -//! <b>Returns</b>: result -//! -//! <b>Note</b>: This function is provided because -//! <i>std::uninitialized_copy</i> from some STL implementations -//! is not compatible with <i>move_iterator</i> -template -<typename I, // I models InputIterator -typename F> // F models ForwardIterator -inline F uninitialized_copy_or_move(I f, I l, F r - /// @cond - ,typename BOOST_MOVE_BOOST_NS::disable_if< move_detail::is_move_iterator<I> >::type* = 0 - /// @endcond - ) -{ - return std::uninitialized_copy(f, l, r); -} - -//! <b>Effects</b>: -//! \code -//! for (; first != last; ++result, ++first) -//! *result = *first; -//! \endcode -//! -//! <b>Returns</b>: result -//! -//! <b>Note</b>: This function is provided because -//! <i>std::uninitialized_copy</i> from some STL implementations -//! is not compatible with <i>move_iterator</i> -template -<typename I, // I models InputIterator -typename F> // F models ForwardIterator -inline F copy_or_move(I f, I l, F r - /// @cond - ,typename BOOST_MOVE_BOOST_NS::disable_if< move_detail::is_move_iterator<I> >::type* = 0 - /// @endcond - ) -{ - return std::copy(f, l, r); -} - -//! If this trait yields to true -//! (<i>has_trivial_destructor_after_move <T>::value == true</i>) -//! means that if T is used as argument of a move construction/assignment, -//! there is no need to call T's destructor. -//! This optimization tipically is used to improve containers' performance. -//! -//! By default this trait is true if the type has trivial destructor, -//! every class should specialize this trait if it wants to improve performance -//! when inserted in containers. -template <class T> -struct has_trivial_destructor_after_move - : BOOST_MOVE_BOOST_NS::has_trivial_destructor<T> -{}; - - - -namespace move_detail { - -// Code from Jeffrey Lee Hellrung, many thanks - -#ifndef BOOST_NO_RVALUE_REFERENCES - template< class T> struct forward_type { typedef T type; }; -#else // #ifndef BOOST_NO_RVALUE_REFERENCES - template< class T> - struct forward_type - { typedef const T &type; }; - - template< class T> - struct forward_type< boost::rv<T> > - { typedef T type; }; -#endif // #ifndef BOOST_NO_RVALUE_REFERENCES - - - -// Code from Jeffrey Lee Hellrung, many thanks - -template< class T > struct is_rvalue_reference : BOOST_MOVE_BOOST_NS::integral_constant<bool, false> { }; -#ifndef BOOST_NO_RVALUE_REFERENCES - template< class T > struct is_rvalue_reference< T&& > : BOOST_MOVE_BOOST_NS::integral_constant<bool, true> { }; -#else // #ifndef BOOST_NO_RVALUE_REFERENCES - template< class T > struct is_rvalue_reference< boost::rv<T>& > - : BOOST_MOVE_BOOST_NS::integral_constant<bool, true> - {}; - - template< class T > struct is_rvalue_reference< const boost::rv<T>& > - : BOOST_MOVE_BOOST_NS::integral_constant<bool, true> - {}; -#endif // #ifndef BOOST_NO_RVALUE_REFERENCES - -#ifndef BOOST_NO_RVALUE_REFERENCES - template< class T > struct add_rvalue_reference { typedef T&& type; }; -#else // #ifndef BOOST_NO_RVALUE_REFERENCES - namespace detail_add_rvalue_reference - { - template< class T - , bool emulation = ::boost::has_move_emulation_enabled<T>::value - , bool rv = ::boost::move_detail::is_rv<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_RVALUE_REFERENCES - -template< class T > struct remove_rvalue_reference { typedef T type; }; - -#ifndef BOOST_NO_RVALUE_REFERENCES - template< class T > struct remove_rvalue_reference< T&& > { typedef T type; }; -#else // #ifndef BOOST_NO_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_RVALUE_REFERENCES - -template <typename T> -typename boost::move_detail::add_rvalue_reference<T>::type declval(); - -} -// 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 boost { - -#if defined BOOST_MSVC - #pragma warning (pop) - #ifdef BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE - #undef BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE - #undef _CRT_SECURE_NO_DEPRECATE - #endif - - #ifdef BOOST_INTERPROCESS_SCL_SECURE_NO_WARNINGS - #undef BOOST_INTERPROCESS_SCL_SECURE_NO_WARNINGS - #undef _SCL_SECURE_NO_WARNINGS - #endif -#endif +#include <boost/move/detail/config_begin.hpp> +#include <boost/move/utility.hpp> +#include <boost/move/iterator.hpp> +#include <boost/move/traits.hpp> +#include <boost/move/algorithm.hpp> +#include <boost/move/detail/config_end.hpp> #endif //#ifndef BOOST_MOVE_MOVE_HPP diff --git a/boost/move/traits.hpp b/boost/move/traits.hpp new file mode 100644 index 0000000000..c4b3afe5bc --- /dev/null +++ b/boost/move/traits.hpp @@ -0,0 +1,72 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2012. +// 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_MOVE_TRAITS_HPP +#define BOOST_MOVE_MOVE_TRAITS_HPP + +#include <boost/move/detail/config_begin.hpp> +#include <boost/type_traits/has_trivial_destructor.hpp> +#include <boost/type_traits/is_nothrow_move_constructible.hpp> +#include <boost/type_traits/is_nothrow_move_assignable.hpp> +#include <boost/type_traits/is_copy_constructible.hpp> +#include <boost/move/detail/meta_utils.hpp> + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#include <boost/move/core.hpp> +#endif + +namespace boost { + +//! If this trait yields to true +//! (<i>has_trivial_destructor_after_move <T>::value == true</i>) +//! means that if T is used as argument of a move construction/assignment, +//! there is no need to call T's destructor. +//! This optimization tipically is used to improve containers' performance. +//! +//! By default this trait is true if the type has trivial destructor, +//! every class should specialize this trait if it wants to improve performance +//! when inserted in containers. +template <class T> +struct has_trivial_destructor_after_move + : ::boost::has_trivial_destructor<T> +{}; + +//! By default this traits returns +//! <pre>boost::is_nothrow_move_constructible<T>::value && boost::is_nothrow_move_assignable<T>::value </pre>. +//! Classes with non-throwing move constructor +//! and assignment can specialize this trait to obtain some performance improvements. +template <class T> +struct has_nothrow_move +{ + static const bool value = boost::is_nothrow_move_constructible<T>::value && + boost::is_nothrow_move_assignable<T>::value; +}; + +namespace move_detail { + +template <class T> +struct is_nothrow_move_constructible_or_uncopyable +{ + //The standard requires is_nothrow_move_constructible for move_if_noexcept + //but a user (usually in C++03) might specialize has_nothrow_move which includes it + static const bool value = boost::is_nothrow_move_constructible<T>::value || + has_nothrow_move<T>::value || + !boost::is_copy_constructible<T>::value; +}; + +} //move_detail { +} //namespace boost { + +#include <boost/move/detail/config_end.hpp> + +#endif //#ifndef BOOST_MOVE_MOVE_TRAITS_HPP diff --git a/boost/move/unique_ptr.hpp b/boost/move/unique_ptr.hpp new file mode 100644 index 0000000000..df10fb3bfe --- /dev/null +++ b/boost/move/unique_ptr.hpp @@ -0,0 +1,855 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2014-2014. 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. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_MOVE_UNIQUE_PTR_HPP_INCLUDED +#define BOOST_MOVE_UNIQUE_PTR_HPP_INCLUDED + +#include <boost/move/detail/config_begin.hpp> +#include <boost/move/detail/workaround.hpp> +#include <boost/move/detail/unique_ptr_meta_utils.hpp> +#include <boost/move/default_delete.hpp> +#include <boost/move/utility_core.hpp> +#include <boost/static_assert.hpp> +#include <boost/assert.hpp> + +#include <cstddef> //For std::nullptr_t and std::size_t + +//!\file +//! Describes the smart pointer unique_ptr, a drop-in replacement for std::unique_ptr, +//! usable also from C++03 compilers. +//! +//! Main differences from std::unique_ptr to avoid heavy dependencies, +//! specially in C++03 compilers: +//! - <tt>operator < </tt> uses pointer <tt>operator < </tt>instead of <tt>std::less<common_type></tt>. +//! This avoids dependencies on <tt>std::common_type</tt> and <tt>std::less</tt> +//! (<tt><type_traits>/<functional></tt> headers. In C++03 this avoid pulling Boost.Typeof and other +//! cascading dependencies. As in all Boost platforms <tt>operator <</tt> on raw pointers and +//! other smart pointers provides strict weak ordering in practice this should not be a problem for users. +//! - assignable from literal 0 for compilers without nullptr +//! - <tt>unique_ptr<T[]></tt> is constructible and assignable from <tt>unique_ptr<U[]></tt> if +//! cv-less T and cv-less U are the same type and T is more CV qualified than U. + +namespace boost{ +namespace move_upd { + +//////////////////////////////////////////// +// deleter types +//////////////////////////////////////////// +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +template <class T> +class is_noncopyable +{ + typedef char true_t; + class false_t { char dummy[2]; }; + template<class U> static false_t dispatch(...); + template<class U> static true_t dispatch(typename U::boost_move_no_copy_constructor_or_assign*); + public: + static const bool value = sizeof(dispatch<T>(0)) == sizeof(true_t); +}; +#endif //defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +template <class D> +struct deleter_types +{ + typedef typename bmupmu::add_lvalue_reference<D>::type del_ref; + typedef typename bmupmu::add_const_lvalue_reference<D>::type del_cref; + #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + typedef typename bmupmu::if_c + < bmupmu::is_lvalue_reference<D>::value, D, del_cref >::type deleter_arg_type1; + typedef typename bmupmu::remove_reference<D>::type && deleter_arg_type2; + #else + typedef typename bmupmu::if_c + < is_noncopyable<D>::value, bmupmu::nat, del_cref>::type non_ref_deleter_arg1; + typedef typename bmupmu::if_c< bmupmu::is_lvalue_reference<D>::value + , D, non_ref_deleter_arg1 >::type deleter_arg_type1; + typedef ::boost::rv<D> & deleter_arg_type2; + #endif +}; + +//////////////////////////////////////////// +// unique_ptr_data +//////////////////////////////////////////// +template <class P, class D, bool = bmupmu::is_unary_function<D>::value || bmupmu::is_reference<D>::value > +struct unique_ptr_data +{ + typedef typename deleter_types<D>::deleter_arg_type1 deleter_arg_type1; + typedef typename deleter_types<D>::del_ref del_ref; + typedef typename deleter_types<D>::del_cref del_cref; + + unique_ptr_data() BOOST_NOEXCEPT + : m_p(), d() + {} + + explicit unique_ptr_data(P p) BOOST_NOEXCEPT + : m_p(p), d() + {} + + unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT + : m_p(p), d(d1) + {} + + template <class U> + unique_ptr_data(P p, BOOST_FWD_REF(U) d) BOOST_NOEXCEPT + : m_p(p), d(::boost::forward<U>(d)) + {} + + del_ref deleter() { return d; } + del_cref deleter() const{ return d; } + + P m_p; + D d; + + private: + unique_ptr_data& operator=(const unique_ptr_data&); + unique_ptr_data(const unique_ptr_data&); +}; + +template <class P, class D> +struct unique_ptr_data<P, D, false> + : private D +{ + typedef typename deleter_types<D>::deleter_arg_type1 deleter_arg_type1; + typedef typename deleter_types<D>::del_ref del_ref; + typedef typename deleter_types<D>::del_cref del_cref; + + unique_ptr_data() BOOST_NOEXCEPT + : D(), m_p() + {} + + explicit unique_ptr_data(P p) BOOST_NOEXCEPT + : D(), m_p(p) + {} + + unique_ptr_data(P p, deleter_arg_type1 d1) BOOST_NOEXCEPT + : D(d1), m_p(p) + {} + + template <class U> + unique_ptr_data(P p, BOOST_FWD_REF(U) d) BOOST_NOEXCEPT + : D(::boost::forward<U>(d)), m_p(p) + {} + + del_ref deleter() BOOST_NOEXCEPT { return static_cast<del_ref>(*this); } + del_cref deleter() const BOOST_NOEXCEPT { return static_cast<del_cref>(*this); } + + P m_p; + + private: + unique_ptr_data& operator=(const unique_ptr_data&); + unique_ptr_data(const unique_ptr_data&); +}; + +//////////////////////////////////////////// +// is_unique_ptr_convertible +//////////////////////////////////////////// + +//Although non-standard, we avoid using pointer_traits +//to avoid heavy dependencies +template <typename T> +struct get_element_type +{ + struct DefaultWrap { typedef bmupmu::natify<T> element_type; }; + template <typename X> static char test(int, typename X::element_type*); + template <typename X> static int test(...); + static const bool value = (1 == sizeof(test<T>(0, 0))); + typedef typename bmupmu::if_c<value, T, DefaultWrap>::type::element_type type; +}; + +template<class T> +struct get_element_type<T*> +{ + typedef T type; +}; + +template<class T> +struct get_cvelement + : bmupmu::remove_cv<typename get_element_type<T>::type> +{}; + +template <class P1, class P2> +struct is_same_cvelement_and_convertible +{ + typedef typename bmupmu::remove_reference<P1>::type arg1; + typedef typename bmupmu::remove_reference<P2>::type arg2; + static const bool same_cvless = + bmupmu::is_same<typename get_cvelement<arg1>::type,typename get_cvelement<arg2>::type>::value; + static const bool value = same_cvless && bmupmu::is_convertible<arg1, arg2>::value; +}; + +template<bool IsArray, class FromPointer, class ThisPointer> +struct is_unique_ptr_convertible + : is_same_cvelement_and_convertible<FromPointer, ThisPointer> +{}; + +template<class FromPointer, class ThisPointer> +struct is_unique_ptr_convertible<false, FromPointer, ThisPointer> + : bmupmu::is_convertible<FromPointer, ThisPointer> +{}; + +//////////////////////////////////////// +//// enable_up_moveconv_assign +//////////////////////////////////////// + +template<class T, class FromPointer, class ThisPointer, class Type = bmupmu::nat> +struct enable_up_ptr + : bmupmu::enable_if_c< is_unique_ptr_convertible + < bmupmu::is_array<T>::value, FromPointer, ThisPointer>::value, Type> +{}; + +//////////////////////////////////////// +//// enable_up_moveconv_assign +//////////////////////////////////////// + +template<class T, class D, class U, class E> +struct unique_moveconvert_assignable +{ + static const bool value = (bmupmu::extent<T>::value == bmupmu::extent<U>::value) && is_unique_ptr_convertible + < bmupmu::is_array<T>::value + , typename bmupmu::pointer_type<U, E>::type, typename bmupmu::pointer_type<T, D>::type>::value; +}; + +template<class T, class D, class U, class E, std::size_t N> +struct unique_moveconvert_assignable<T[], D, U[N], E> + : unique_moveconvert_assignable<T[], D, U[], E> +{}; + +template<class T, class D, class U, class E, class Type = bmupmu::nat> +struct enable_up_moveconv_assign + : bmupmu::enable_if_c<unique_moveconvert_assignable<T, D, U, E>::value, Type> +{}; + +//////////////////////////////////////// +//// enable_up_moveconv_constr +//////////////////////////////////////// + +template<class D, class E, bool IsReference = bmupmu::is_reference<D>::value> +struct unique_deleter_is_initializable + : bmupmu::is_same<D, E> +{}; + +template <class T, class U> +class is_rvalue_convertible +{ + #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + typedef typename bmupmu::remove_reference<T>::type&& t_from; + #else + typedef typename bmupmu::if_c + < ::boost::has_move_emulation_enabled<T>::value && !bmupmu::is_reference<T>::value + , ::boost::rv<T>& + , typename bmupmu::add_lvalue_reference<T>::type + >::type t_from; + #endif + + typedef char true_t; + class false_t { char dummy[2]; }; + static false_t dispatch(...); + static true_t dispatch(U); + static t_from trigger(); + public: + static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t); +}; + +template<class D, class E> +struct unique_deleter_is_initializable<D, E, false> +{ + #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + //Clang has some problems with is_rvalue_convertible with non-copyable types + //so use intrinsic if available + #if defined(BOOST_CLANG) + #if __has_feature(is_convertible_to) + static const bool value = __is_convertible_to(E, D); + #else + static const bool value = is_rvalue_convertible<E, D>::value; + #endif + #else + static const bool value = is_rvalue_convertible<E, D>::value; + #endif + + #else //!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + //No hope for compilers with move emulation for now. In several compilers is_convertible + // leads to errors, so just move the Deleter and see if the conversion works + static const bool value = true; /*is_rvalue_convertible<E, D>::value*/ + #endif +}; + +template<class T, class D, class U, class E, class Type = bmupmu::nat> +struct enable_up_moveconv_constr + : bmupmu::enable_if_c<unique_moveconvert_assignable<T, D, U, E>::value && + unique_deleter_is_initializable<D, E>::value, Type> +{}; + +} //namespace move_upd { + +namespace movelib { + +//! A unique pointer is an object that owns another object and +//! manages that other object through a pointer. +//! +//! More precisely, a unique pointer is an object u that stores a pointer to a second object p and will dispose +//! of p when u is itself destroyed (e.g., when leaving block scope). In this context, u is said to own p. +//! +//! The mechanism by which u disposes of p is known as p's associated deleter, a function object whose correct +//! invocation results in p's appropriate disposition (typically its deletion). +//! +//! Let the notation u.p denote the pointer stored by u, and let u.d denote the associated deleter. Upon request, +//! u can reset (replace) u.p and u.d with another pointer and deleter, but must properly dispose of its owned +//! object via the associated deleter before such replacement is considered completed. +//! +//! Additionally, u can, upon request, transfer ownership to another unique pointer u2. Upon completion of +//! such a transfer, the following postconditions hold: +//! - u2.p is equal to the pre-transfer u.p, +//! - u.p is equal to nullptr, and +//! - if the pre-transfer u.d maintained state, such state has been transferred to u2.d. +//! +//! As in the case of a reset, u2 must properly dispose of its pre-transfer owned object via the pre-transfer +//! associated deleter before the ownership transfer is considered complete. +//! +//! Each object of a type U instantiated from the unique_ptr template specified in this subclause has the strict +//! ownership semantics, specified above, of a unique pointer. In partial satisfaction of these semantics, each +//! such U is MoveConstructible and MoveAssignable, but is not CopyConstructible nor CopyAssignable. +//! The template parameter T of unique_ptr may be an incomplete type. +//! +//! The uses of unique_ptr include providing exception safety for dynamically allocated memory, passing +//! ownership of dynamically allocated memory to a function, and returning dynamically allocated memory from +//! a function. +//! +//! If T is an array type (e.g. unique_ptr<MyType[]>) the interface is slightly altered: +//! - Pointers to types derived from T are rejected by the constructors, and by reset. +//! - The observers <tt>operator*</tt> and <tt>operator-></tt> are not provided. +//! - The indexing observer <tt>operator[]</tt> is provided. +//! +//! \tparam T Provides the type of the stored pointer. +//! \tparam D The deleter type: +//! - The default type for the template parameter D is default_delete. A client-supplied template argument +//! D shall be a function object type, lvalue-reference to function, or lvalue-reference to function object type +//! for which, given a value d of type D and a value ptr of type unique_ptr<T, D>::pointer, the expression +//! d(ptr) is valid and has the effect of disposing of the pointer as appropriate for that deleter. +//! - If the deleter's type D is not a reference type, D shall satisfy the requirements of Destructible. +//! - If the type <tt>remove_reference<D>::type::pointer</tt> exists, it shall satisfy the requirements of NullablePointer. +template <class T, class D = default_delete<T> > +class unique_ptr +{ + #if defined(BOOST_MOVE_DOXYGEN_INVOKED) + public: + unique_ptr(const unique_ptr&) = delete; + unique_ptr& operator=(const unique_ptr&) = delete; + private: + #else + BOOST_MOVABLE_BUT_NOT_COPYABLE(unique_ptr) + + typedef bmupmu::pointer_type<T, D > pointer_type_obtainer; + typedef bmupd::unique_ptr_data + <typename pointer_type_obtainer::type, D> data_type; + typedef typename bmupd::deleter_types<D>::deleter_arg_type1 deleter_arg_type1; + typedef typename bmupd::deleter_types<D>::deleter_arg_type2 deleter_arg_type2; + data_type m_data; + #endif + + public: + //! If the type <tt>remove_reference<D>::type::pointer</tt> exists, then it shall be a + //! synonym for <tt>remove_reference<D>::type::pointer</tt>. Otherwise it shall be a + //! synonym for T*. + typedef typename BOOST_MOVE_SEEDOC(pointer_type_obtainer::type) pointer; + //! If T is an array type, then element_type is equal to T. Otherwise, if T is a type + //! in the form U[], element_type is equal to U. + typedef typename BOOST_MOVE_SEEDOC(bmupmu::remove_extent<T>::type) element_type; + typedef D deleter_type; + + //! <b>Requires</b>: D shall satisfy the requirements of DefaultConstructible, and + //! that construction shall not throw an exception. + //! + //! <b>Effects</b>: Constructs a unique_ptr object that owns nothing, value-initializing the + //! stored pointer and the stored deleter. + //! + //! <b>Postconditions</b>: <tt>get() == nullptr</tt>. <tt>get_deleter()</tt> returns a reference to the stored deleter. + //! + //! <b>Remarks</b>: If this constructor is instantiated with a pointer type or reference type + //! for the template argument D, the program is ill-formed. + BOOST_CONSTEXPR unique_ptr() BOOST_NOEXCEPT + : m_data() + { + //If this constructor is instantiated with a pointer type or reference type + //for the template argument D, the program is ill-formed. + BOOST_STATIC_ASSERT(!bmupmu::is_pointer<D>::value); + BOOST_STATIC_ASSERT(!bmupmu::is_reference<D>::value); + } + + //! <b>Effects</b>: Same as <tt>unique_ptr()</tt> (default constructor). + //! + BOOST_CONSTEXPR unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT + : m_data() + { + //If this constructor is instantiated with a pointer type or reference type + //for the template argument D, the program is ill-formed. + BOOST_STATIC_ASSERT(!bmupmu::is_pointer<D>::value); + BOOST_STATIC_ASSERT(!bmupmu::is_reference<D>::value); + } + + //! <b>Requires</b>: D shall satisfy the requirements of DefaultConstructible, and + //! that construction shall not throw an exception. + //! + //! <b>Effects</b>: Constructs a unique_ptr which owns p, initializing the stored pointer + //! with p and value initializing the stored deleter. + //! + //! <b>Postconditions</b>: <tt>get() == p</tt>. <tt>get_deleter()</tt> returns a reference to the stored deleter. + //! + //! <b>Remarks</b>: If this constructor is instantiated with a pointer type or reference type + //! for the template argument D, the program is ill-formed. + //! This constructor shall not participate in overload resolution unless: + //! - If T is not an array type and Pointer is implicitly convertible to pointer. + //! - If T is an array type and Pointer is a more CV qualified pointer to element_type. + template<class Pointer> + explicit unique_ptr(Pointer p + BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer>::type* =0) + ) BOOST_NOEXCEPT + : m_data(p) + { + //If T is not an array type, element_type_t<Pointer> derives from T + //it uses the default deleter and T has no virtual destructor, then you have a problem + BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor + <D, typename bmupd::get_element_type<Pointer>::type>::value )); + //If this constructor is instantiated with a pointer type or reference type + //for the template argument D, the program is ill-formed. + BOOST_STATIC_ASSERT(!bmupmu::is_pointer<D>::value); + BOOST_STATIC_ASSERT(!bmupmu::is_reference<D>::value); + } + + //!The signature of this constructor depends upon whether D is a reference type. + //! - If D is non-reference type A, then the signature is <tt>unique_ptr(pointer p, const A& d)</tt>. + //! - If D is an lvalue-reference type A&, then the signature is <tt>unique_ptr(pointer p, A& d)</tt>. + //! - If D is an lvalue-reference type const A&, then the signature is <tt>unique_ptr(pointer p, const A& d)</tt>. + //! + //! + //! <b>Requires</b>: Either + //! - D is not an lvalue-reference type and d is an lvalue or const rvalue. + //! D shall satisfy the requirements of CopyConstructible, and the copy constructor of D + //! shall not throw an exception. This unique_ptr will hold a copy of d. + //! - D is an lvalue-reference type and d is an lvalue. the type which D references need not be CopyConstructible nor + //! MoveConstructible. This unique_ptr will hold a D which refers to the lvalue d. + //! + //! <b>Effects</b>: Constructs a unique_ptr object which owns p, initializing the stored pointer with p and + //! initializing the deleter as described above. + //! + //! <b>Postconditions</b>: <tt>get() == p</tt>. <tt>get_deleter()</tt> returns a reference to the stored deleter. If D is a + //! reference type then <tt>get_deleter()</tt> returns a reference to the lvalue d. + //! + //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless: + //! - If T is not an array type and Pointer is implicitly convertible to pointer. + //! - If T is an array type and Pointer is a more CV qualified pointer to element_type. + template<class Pointer> + unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type1) d1 + BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer>::type* =0) + ) BOOST_NOEXCEPT + : m_data(p, d1) + { + //If T is not an array type, element_type_t<Pointer> derives from T + //it uses the default deleter and T has no virtual destructor, then you have a problem + BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor + <D, typename bmupd::get_element_type<Pointer>::type>::value )); + } + + //! <b>Effects</b>: Same effects as <tt>template<class Pointer> unique_ptr(Pointer p, deleter_arg_type1 d1)</tt> + //! and additionally <tt>get() == nullptr</tt> + unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type1) d1) BOOST_NOEXCEPT + : m_data(pointer(), d1) + {} + + //! The signature of this constructor depends upon whether D is a reference type. + //! - If D is non-reference type A, then the signature is <tt>unique_ptr(pointer p, A&& d)</tt>. + //! - If D is an lvalue-reference type A&, then the signature is <tt>unique_ptr(pointer p, A&& d)</tt>. + //! - If D is an lvalue-reference type const A&, then the signature is <tt>unique_ptr(pointer p, const A&& d)</tt>. + //! + //! <b>Requires</b>: Either + //! - D is not an lvalue-reference type and d is a non-const rvalue. D + //! shall satisfy the requirements of MoveConstructible, and the move constructor + //! of D shall not throw an exception. This unique_ptr will hold a value move constructed from d. + //! - D is an lvalue-reference type and d is an rvalue, the program is ill-formed. + //! + //! <b>Effects</b>: Constructs a unique_ptr object which owns p, initializing the stored pointer with p and + //! initializing the deleter as described above. + //! + //! <b>Postconditions</b>: <tt>get() == p</tt>. <tt>get_deleter()</tt> returns a reference to the stored deleter. If D is a + //! reference type then <tt>get_deleter()</tt> returns a reference to the lvalue d. + //! + //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless: + //! - If T is not an array type and Pointer is implicitly convertible to pointer. + //! - If T is an array type and Pointer is a more CV qualified pointer to element_type. + template<class Pointer> + unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type2) d2 + BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer>::type* =0) + ) BOOST_NOEXCEPT + : m_data(p, ::boost::move(d2)) + { + //If T is not an array type, element_type_t<Pointer> derives from T + //it uses the default deleter and T has no virtual destructor, then you have a problem + BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor + <D, typename bmupd::get_element_type<Pointer>::type>::value )); + } + + //! <b>Effects</b>: Same effects as <tt>template<class Pointer> unique_ptr(Pointer p, deleter_arg_type2 d2)</tt> + //! and additionally <tt>get() == nullptr</tt> + unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type2) d2) BOOST_NOEXCEPT + : m_data(pointer(), ::boost::move(d2)) + {} + + //! <b>Requires</b>: If D is not a reference type, D shall satisfy the requirements of MoveConstructible. + //! Construction of the deleter from an rvalue of type D shall not throw an exception. + //! + //! <b>Effects</b>: Constructs a unique_ptr by transferring ownership from u to *this. If D is a reference type, + //! this deleter is copy constructed from u's deleter; otherwise, this deleter is move constructed from u's + //! deleter. + //! + //! <b>Postconditions</b>: <tt>get()</tt> yields the value u.get() yielded before the construction. <tt>get_deleter()</tt> + //! returns a reference to the stored deleter that was constructed from u.get_deleter(). If D is a + //! reference type then <tt>get_deleter()</tt> and <tt>u.get_deleter()</tt> both reference the same lvalue deleter. + unique_ptr(BOOST_RV_REF(unique_ptr) u) BOOST_NOEXCEPT + : m_data(u.release(), ::boost::move_if_not_lvalue_reference<D>(u.get_deleter())) + {} + + //! <b>Requires</b>: If E is not a reference type, construction of the deleter from an rvalue of type E shall be + //! well formed and shall not throw an exception. Otherwise, E is a reference type and construction of the + //! deleter from an lvalue of type E shall be well formed and shall not throw an exception. + //! + //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless: + //! - <tt>unique_ptr<U, E>::pointer</tt> is implicitly convertible to pointer, + //! - U is not an array type, and + //! - either D is a reference type and E is the same type as D, or D is not a reference type and E is + //! implicitly convertible to D. + //! + //! <b>Effects</b>: Constructs a unique_ptr by transferring ownership from u to *this. If E is a reference type, + //! this deleter is copy constructed from u's deleter; otherwise, this deleter is move constructed from u's deleter. + //! + //! <b>Postconditions</b>: <tt>get()</tt> yields the value <tt>u.get()</tt> yielded before the construction. <tt>get_deleter()</tt> + //! returns a reference to the stored deleter that was constructed from <tt>u.get_deleter()</tt>. + template <class U, class E> + unique_ptr( BOOST_RV_REF_BEG unique_ptr<U, E> BOOST_RV_REF_END u + BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_moveconv_constr<T BOOST_MOVE_I D BOOST_MOVE_I U BOOST_MOVE_I E>::type* =0) + ) BOOST_NOEXCEPT + : m_data(u.release(), ::boost::move_if_not_lvalue_reference<E>(u.get_deleter())) + { + //If T is not an array type, U derives from T + //it uses the default deleter and T has no virtual destructor, then you have a problem + BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor + <D, typename unique_ptr<U, E>::pointer>::value )); + } + + //! <b>Requires</b>: The expression <tt>get_deleter()(get())</tt> shall be well formed, shall have well-defined behavior, + //! and shall not throw exceptions. + //! + //! <b>Effects</b>: If <tt>get() == nullpt1r</tt> there are no effects. Otherwise <tt>get_deleter()(get())</tt>. + //! + //! <b>Note</b>: The use of default_delete requires T to be a complete type + ~unique_ptr() + { if(m_data.m_p) m_data.deleter()(m_data.m_p); } + + //! <b>Requires</b>: If D is not a reference type, D shall satisfy the requirements of MoveAssignable + //! and assignment of the deleter from an rvalue of type D shall not throw an exception. Otherwise, D + //! is a reference type; <tt>remove_reference<D>::type</tt> shall satisfy the CopyAssignable requirements and + //! assignment of the deleter from an lvalue of type D shall not throw an exception. + //! + //! <b>Effects</b>: Transfers ownership from u to *this as if by calling <tt>reset(u.release())</tt> followed + //! by <tt>get_deleter() = std::forward<D>(u.get_deleter())</tt>. + //! + //! <b>Returns</b>: *this. + unique_ptr& operator=(BOOST_RV_REF(unique_ptr) u) BOOST_NOEXCEPT + { + this->reset(u.release()); + m_data.deleter() = ::boost::move_if_not_lvalue_reference<D>(u.get_deleter()); + return *this; + } + + //! <b>Requires</b>: If E is not a reference type, assignment of the deleter from an rvalue of type E shall be + //! well-formed and shall not throw an exception. Otherwise, E is a reference type and assignment of the + //! deleter from an lvalue of type E shall be well-formed and shall not throw an exception. + //! + //! <b>Remarks</b>: This operator shall not participate in overload resolution unless: + //! - <tt>unique_ptr<U, E>::pointer</tt> is implicitly convertible to pointer and + //! - U is not an array type. + //! + //! <b>Effects</b>: Transfers ownership from u to *this as if by calling <tt>reset(u.release())</tt> followed by + //! <tt>get_deleter() = std::forward<E>(u.get_deleter())</tt>. + //! + //! <b>Returns</b>: *this. + template <class U, class E> + BOOST_MOVE_DOC1ST(unique_ptr&, typename bmupd::enable_up_moveconv_assign + <T BOOST_MOVE_I D BOOST_MOVE_I U BOOST_MOVE_I E BOOST_MOVE_I unique_ptr &>::type) + operator=(BOOST_RV_REF_BEG unique_ptr<U, E> BOOST_RV_REF_END u) BOOST_NOEXCEPT + { + this->reset(u.release()); + m_data.deleter() = ::boost::move_if_not_lvalue_reference<E>(u.get_deleter()); + return *this; + } + + //! <b>Effects</b>: <tt>reset()</tt>. + //! + //! <b>Postcondition</b>: <tt>get() == nullptr</tt> + //! + //! <b>Returns</b>: *this. + unique_ptr& operator=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT + { this->reset(); return *this; } + + //! <b>Requires</b>: <tt>get() != nullptr</tt>. + //! + //! <b>Returns</b>: <tt>*get()</tt>. + //! + //! <b>Remarks</b: If T is an array type, the program is ill-formed. + BOOST_MOVE_DOC1ST(element_type&, typename bmupmu::add_lvalue_reference<element_type>::type) + operator*() const BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT((!bmupmu::is_array<T>::value)); + return *m_data.m_p; + } + + //! <b>Requires</b>: i < the number of elements in the array to which the stored pointer points. + //! + //! <b>Returns</b>: <tt>get()[i]</tt>. + //! + //! <b>Remarks</b: If T is not an array type, the program is ill-formed. + BOOST_MOVE_DOC1ST(element_type&, typename bmupmu::add_lvalue_reference<element_type>::type) + operator[](std::size_t i) const BOOST_NOEXCEPT + { + BOOST_ASSERT( bmupmu::extent<T>::value == 0 || i < bmupmu::extent<T>::value ); + BOOST_ASSERT(m_data.m_p); + return m_data.m_p[i]; + } + + //! <b>Requires</b>: <tt>get() != nullptr</tt>. + //! + //! <b>Returns</b>: <tt>get()</tt>. + //! + //! <b>Note</b>: use typically requires that T be a complete type. + //! + //! <b>Remarks</b: If T is an array type, the program is ill-formed. + pointer operator->() const BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT((!bmupmu::is_array<T>::value)); + BOOST_ASSERT(m_data.m_p); + return m_data.m_p; + } + + //! <b>Returns</b>: The stored pointer. + //! + pointer get() const BOOST_NOEXCEPT + { return m_data.m_p; } + + //! <b>Returns</b>: A reference to the stored deleter. + //! + BOOST_MOVE_DOC1ST(D&, typename bmupmu::add_lvalue_reference<D>::type) + get_deleter() BOOST_NOEXCEPT + { return m_data.deleter(); } + + //! <b>Returns</b>: A reference to the stored deleter. + //! + BOOST_MOVE_DOC1ST(const D&, typename bmupmu::add_const_lvalue_reference<D>::type) + get_deleter() const BOOST_NOEXCEPT + { return m_data.deleter(); } + + #ifdef BOOST_MOVE_DOXYGEN_INVOKED + //! <b>Returns</b>: Returns: get() != nullptr. + //! + explicit operator bool + #else + operator bmupd::explicit_bool_arg + #endif + ()const BOOST_NOEXCEPT + { + return m_data.m_p + ? &bmupd::bool_conversion::for_bool + : bmupd::explicit_bool_arg(0); + } + + //! <b>Postcondition</b>: <tt>get() == nullptr</tt>. + //! + //! <b>Returns</b>: The value <tt>get()</tt> had at the start of the call to release. + pointer release() BOOST_NOEXCEPT + { + const pointer tmp = m_data.m_p; + m_data.m_p = pointer(); + return tmp; + } + + //! <b>Requires</b>: The expression <tt>get_deleter()(get())</tt> shall be well formed, shall have well-defined behavior, + //! and shall not throw exceptions. + //! + //! <b>Effects</b>: assigns p to the stored pointer, and then if the old value of the stored pointer, old_p, was not + //! equal to nullptr, calls <tt>get_deleter()(old_p)</tt>. Note: The order of these operations is significant + //! because the call to <tt>get_deleter()</tt> may destroy *this. + //! + //! <b>Postconditions</b>: <tt>get() == p</tt>. Note: The postcondition does not hold if the call to <tt>get_deleter()</tt> + //! destroys *this since <tt>this->get()</tt> is no longer a valid expression. + //! + //! <b>Remarks</b>: This constructor shall not participate in overload resolution unless: + //! - If T is not an array type and Pointer is implicitly convertible to pointer. + //! - If T is an array type and Pointer is a more CV qualified pointer to element_type. + template<class Pointer> + BOOST_MOVE_DOC1ST(void, typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer BOOST_MOVE_I void>::type) + reset(Pointer p) BOOST_NOEXCEPT + { + //If T is not an array type, element_type_t<Pointer> derives from T + //it uses the default deleter and T has no virtual destructor, then you have a problem + BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor + <D, typename bmupd::get_element_type<Pointer>::type>::value )); + pointer tmp = m_data.m_p; + m_data.m_p = p; + if(tmp) m_data.deleter()(tmp); + } + + //! <b>Requires</b>: The expression <tt>get_deleter()(get())</tt> shall be well formed, shall have well-defined behavior, + //! and shall not throw exceptions. + //! + //! <b>Effects</b>: assigns nullptr to the stored pointer, and then if the old value of the stored pointer, old_p, was not + //! equal to nullptr, calls <tt>get_deleter()(old_p)</tt>. Note: The order of these operations is significant + //! because the call to <tt>get_deleter()</tt> may destroy *this. + //! + //! <b>Postconditions</b>: <tt>get() == p</tt>. Note: The postcondition does not hold if the call to <tt>get_deleter()</tt> + //! destroys *this since <tt>this->get()</tt> is no longer a valid expression. + void reset() BOOST_NOEXCEPT + { this->reset(pointer()); } + + //! <b>Effects</b>: Same as <tt>reset()</tt> + //! + void reset(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT + { this->reset(); } + + //! <b>Requires</b>: <tt>get_deleter()</tt> shall be swappable and shall not throw an exception under swap. + //! + //! <b>Effects</b>: Invokes swap on the stored pointers and on the stored deleters of *this and u. + void swap(unique_ptr& u) BOOST_NOEXCEPT + { + using ::boost::move_detail::swap; + swap(m_data.m_p, u.m_data.m_p); + swap(m_data.deleter(), u.m_data.deleter()); + } +}; + +//! <b>Effects</b>: Calls <tt>x.swap(y)</tt>. +//! +template <class T, class D> +inline void swap(unique_ptr<T, D> &x, unique_ptr<T, D> &y) BOOST_NOEXCEPT +{ x.swap(y); } + +//! <b>Returns</b>: <tt>x.get() == y.get()</tt>. +//! +template <class T1, class D1, class T2, class D2> +inline bool operator==(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y) +{ return x.get() == y.get(); } + +//! <b>Returns</b>: <tt>x.get() != y.get()</tt>. +//! +template <class T1, class D1, class T2, class D2> +inline bool operator!=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y) +{ return x.get() != y.get(); } + +//! <b>Returns</b>: x.get() < y.get(). +//! +//! <b>Remarks</b>: This comparison shall induce a +//! strict weak ordering betwen pointers. +template <class T1, class D1, class T2, class D2> +inline bool operator<(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y) +{ return x.get() < y.get(); } + +//! <b>Returns</b>: !(y < x). +//! +template <class T1, class D1, class T2, class D2> +inline bool operator<=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y) +{ return !(y < x); } + +//! <b>Returns</b>: y < x. +//! +template <class T1, class D1, class T2, class D2> +inline bool operator>(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y) +{ return y < x; } + +//! <b>Returns</b>:!(x < y). +//! +template <class T1, class D1, class T2, class D2> +inline bool operator>=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y) +{ return !(x < y); } + +//! <b>Returns</b>:!x. +//! +template <class T, class D> +inline bool operator==(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT +{ return !x; } + +//! <b>Returns</b>:!x. +//! +template <class T, class D> +inline bool operator==(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x) BOOST_NOEXCEPT +{ return !x; } + +//! <b>Returns</b>: (bool)x. +//! +template <class T, class D> +inline bool operator!=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT +{ return !!x; } + +//! <b>Returns</b>: (bool)x. +//! +template <class T, class D> +inline bool operator!=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x) BOOST_NOEXCEPT +{ return !!x; } + +//! <b>Requires</b>: <tt>operator </tt> shall induce a strict weak ordering on unique_ptr<T, D>::pointer values. +//! +//! <b>Returns</b>: Returns <tt>x.get() < pointer()</tt>. +template <class T, class D> +inline bool operator<(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) +{ return x.get() < typename unique_ptr<T, D>::pointer(); } + +//! <b>Requires</b>: <tt>operator </tt> shall induce a strict weak ordering on unique_ptr<T, D>::pointer values. +//! +//! <b>Returns</b>: Returns <tt>pointer() < x.get()</tt>. +template <class T, class D> +inline bool operator<(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x) +{ return typename unique_ptr<T, D>::pointer() < x.get(); } + +//! <b>Returns</b>: <tt>nullptr < x</tt>. +//! +template <class T, class D> +inline bool operator>(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) +{ return x.get() > typename unique_ptr<T, D>::pointer(); } + +//! <b>Returns</b>: <tt>x < nullptr</tt>. +//! +template <class T, class D> +inline bool operator>(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x) +{ return typename unique_ptr<T, D>::pointer() > x.get(); } + +//! <b>Returns</b>: <tt>!(nullptr < x)</tt>. +//! +template <class T, class D> +inline bool operator<=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) +{ return !(bmupd::nullptr_type() < x); } + +//! <b>Returns</b>: <tt>!(x < nullptr)</tt>. +//! +template <class T, class D> +inline bool operator<=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x) +{ return !(x < bmupd::nullptr_type()); } + +//! <b>Returns</b>: <tt>!(x < nullptr)</tt>. +//! +template <class T, class D> +inline bool operator>=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) +{ return !(x < bmupd::nullptr_type()); } + +//! <b>Returns</b>: <tt>!(nullptr < x)</tt>. +//! +template <class T, class D> +inline bool operator>=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr<T, D> &x) +{ return !(bmupd::nullptr_type() < x); } + +} //namespace movelib { +} //namespace boost{ + +#include <boost/move/detail/config_end.hpp> + +#endif //#ifndef BOOST_MOVE_UNIQUE_PTR_HPP_INCLUDED diff --git a/boost/move/utility.hpp b/boost/move/utility.hpp new file mode 100644 index 0000000000..a1ddd26b09 --- /dev/null +++ b/boost/move/utility.hpp @@ -0,0 +1,141 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2012. +// 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 +//! This header includes core utilities from <tt><boost/move/utility_core.hpp></tt> and defines +//! some more advanced utilities such as: + +#ifndef BOOST_MOVE_MOVE_UTILITY_HPP +#define BOOST_MOVE_MOVE_UTILITY_HPP + +#include <boost/move/detail/config_begin.hpp> +#include <boost/move/utility_core.hpp> +#include <boost/move/traits.hpp> + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED) + + namespace boost { + + ////////////////////////////////////////////////////////////////////////////// + // + // move_if_noexcept() + // + ////////////////////////////////////////////////////////////////////////////// + + template <class T> + inline typename ::boost::move_detail::enable_if_c + < enable_move_utility_emulation<T>::value && !has_move_emulation_enabled<T>::value + , typename ::boost::move_detail::add_const<T>::type & + >::type + move_if_noexcept(T& x) BOOST_NOEXCEPT + { + return x; + } + + template <class T> + inline typename ::boost::move_detail::enable_if_c + < enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value + && ::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value, rv<T>&>::type + move_if_noexcept(T& x) BOOST_NOEXCEPT + { + return *static_cast<rv<T>* >(::boost::move_detail::addressof(x)); + } + + template <class T> + inline typename ::boost::move_detail::enable_if_c + < enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value + && ::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value + , rv<T>& + >::type + move_if_noexcept(rv<T>& x) BOOST_NOEXCEPT + { + return x; + } + + template <class T> + inline typename ::boost::move_detail::enable_if_c + < enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value + && !::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value + , typename ::boost::move_detail::add_const<T>::type & + >::type + move_if_noexcept(T& x) BOOST_NOEXCEPT + { + return x; + } + + template <class T> + inline typename ::boost::move_detail::enable_if_c + < enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value + && !::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value + , typename ::boost::move_detail::add_const<T>::type & + >::type + move_if_noexcept(rv<T>& x) BOOST_NOEXCEPT + { + return x; + } + + } //namespace boost + +#else //#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED) + + #if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE) + #include <utility> + + namespace boost{ + + using ::std::move_if_noexcept; + + } //namespace boost + + #else //!BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE + + namespace boost { + + ////////////////////////////////////////////////////////////////////////////// + // + // move_if_noexcept() + // + ////////////////////////////////////////////////////////////////////////////// + #if defined(BOOST_MOVE_DOXYGEN_INVOKED) + //! This function provides a way to convert a reference into a rvalue reference + //! in compilers with rvalue references. For other compilers converts T & into + //! <i>::boost::rv<T> &</i> so that move emulation is activated. Reference + //! would be converted to rvalue reference only if input type is nothrow move + //! constructible or if it has no copy constructor. In all other cases const + //! reference would be returned + template <class T> + rvalue_reference_or_const_lvalue_reference move_if_noexcept(input_reference) noexcept; + + #else //BOOST_MOVE_DOXYGEN_INVOKED + + template <class T> + typename ::boost::move_detail::enable_if_c + < ::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value, T&&>::type + move_if_noexcept(T& x) BOOST_NOEXCEPT + { return ::boost::move(x); } + + template <class T> + typename ::boost::move_detail::enable_if_c + < !::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value, const T&>::type + move_if_noexcept(T& x) BOOST_NOEXCEPT + { return x; } + + #endif //BOOST_MOVE_DOXYGEN_INVOKED + + } //namespace boost { + + #endif //#if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE) + +#endif //BOOST_NO_CXX11_RVALUE_REFERENCES + +#include <boost/move/detail/config_end.hpp> + +#endif //#ifndef BOOST_MOVE_MOVE_UTILITY_HPP diff --git a/boost/move/utility_core.hpp b/boost/move/utility_core.hpp new file mode 100644 index 0000000000..ae17fd31b5 --- /dev/null +++ b/boost/move/utility_core.hpp @@ -0,0 +1,295 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2012. +// 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 +//! This header defines core utilities to ease the development +//! of move-aware functions. This header minimizes dependencies +//! from other libraries. + +#ifndef BOOST_MOVE_MOVE_UTILITY_CORE_HPP +#define BOOST_MOVE_MOVE_UTILITY_CORE_HPP + +#include <boost/move/detail/config_begin.hpp> +#include <boost/move/core.hpp> +#include <boost/move/detail/meta_utils.hpp> +#include <boost/static_assert.hpp> + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED) + + namespace boost { + + template<class T> + struct enable_move_utility_emulation + { + static const bool value = true; + }; + + ////////////////////////////////////////////////////////////////////////////// + // + // move() + // + ////////////////////////////////////////////////////////////////////////////// + + template <class T> + inline typename ::boost::move_detail::enable_if_c + < enable_move_utility_emulation<T>::value && !has_move_emulation_enabled<T>::value, T&>::type + move(T& x) BOOST_NOEXCEPT + { + return x; + } + + template <class T> + inline typename ::boost::move_detail::enable_if_c + < enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value, rv<T>&>::type + move(T& x) BOOST_NOEXCEPT + { + return *static_cast<rv<T>* >(::boost::move_detail::addressof(x)); + } + + template <class T> + inline typename ::boost::move_detail::enable_if_c + < enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value, rv<T>&>::type + move(rv<T>& x) BOOST_NOEXCEPT + { + return x; + } + + ////////////////////////////////////////////////////////////////////////////// + // + // forward() + // + ////////////////////////////////////////////////////////////////////////////// + + template <class T> + inline typename ::boost::move_detail::enable_if_c + < enable_move_utility_emulation<T>::value && ::boost::move_detail::is_rv<T>::value, T &>::type + forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT + { + return const_cast<T&>(x); + } + + template <class T> + inline typename ::boost::move_detail::enable_if_c + < enable_move_utility_emulation<T>::value && !::boost::move_detail::is_rv<T>::value, const T &>::type + forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT + { + return x; + } + + ////////////////////////////////////////////////////////////////////////////// + // + // move_if_not_lvalue_reference() + // + ////////////////////////////////////////////////////////////////////////////// + + template <class T> + inline typename ::boost::move_detail::enable_if_c + < enable_move_utility_emulation<T>::value && + ::boost::move_detail::is_rv<T>::value + , T &>::type + move_if_not_lvalue_reference(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT + { + return const_cast<T&>(x); + } + + template <class T> + inline typename ::boost::move_detail::enable_if_c + < enable_move_utility_emulation<T>::value && + !::boost::move_detail::is_rv<T>::value && + (::boost::move_detail::is_lvalue_reference<T>::value || + !has_move_emulation_enabled<T>::value) + , typename ::boost::move_detail::add_lvalue_reference<T>::type + >::type + move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type &x) BOOST_NOEXCEPT + { + return x; + } + + template <class T> + inline typename ::boost::move_detail::enable_if_c + < enable_move_utility_emulation<T>::value && + !::boost::move_detail::is_rv<T>::value && + (!::boost::move_detail::is_lvalue_reference<T>::value && + has_move_emulation_enabled<T>::value) + , rv<T>& + >::type + move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type &x) BOOST_NOEXCEPT + { + return move(x); + } + + } //namespace boost + +#else //#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED) + + #if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE) + #include <utility> + + namespace boost{ + + using ::std::move; + using ::std::forward; + + } //namespace boost + + #else //!BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE + + namespace boost { + + //! This trait's internal boolean `value` is false in compilers with rvalue references + //! and true in compilers without rvalue references. + //! + //! A user can specialize this trait for a type T to false to SFINAE out `move` and `forward` + //! so that the user can define a different move emulation for that type in namespace boost + //! (e.g. another Boost library for its types) and avoid any overload ambiguity. + template<class T> + struct enable_move_utility_emulation + { + static const bool value = false; + }; + + ////////////////////////////////////////////////////////////////////////////// + // + // move + // + ////////////////////////////////////////////////////////////////////////////// + + #if defined(BOOST_MOVE_DOXYGEN_INVOKED) + //! This function provides a way to convert a reference into a rvalue reference + //! in compilers with rvalue references. For other compilers if `T` is Boost.Move + //! enabled type then it converts `T&` into <tt>::boost::rv<T> &</tt> so that + //! move emulation is activated, else it returns `T &`. + template <class T> + rvalue_reference move(input_reference) noexcept; + + #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) + + //Old move approach, lvalues could bind to rvalue references + template <class T> + inline typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT + { return t; } + + #else //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES + + template <class T> + inline typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT + { return static_cast<typename ::boost::move_detail::remove_reference<T>::type &&>(t); } + + #endif //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES + + ////////////////////////////////////////////////////////////////////////////// + // + // forward + // + ////////////////////////////////////////////////////////////////////////////// + + + #if defined(BOOST_MOVE_DOXYGEN_INVOKED) + //! This function provides limited form of forwarding that is usually enough for + //! in-place construction and avoids the exponential overloading for + //! achieve the limited forwarding in C++03. + //! + //! For compilers with rvalue references this function provides perfect forwarding. + //! + //! Otherwise: + //! * If input_reference binds to const ::boost::rv<T> & then it output_reference is + //! ::boost::rv<T> & + //! + //! * Else, output_reference is equal to input_reference. + template <class T> output_reference forward(input_reference) noexcept; + #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) + + //Old move approach, lvalues could bind to rvalue references + + template <class T> + inline T&& forward(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT + { return t; } + + #else //Old move + + template <class T> + inline T&& forward(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT + { return static_cast<T&&>(t); } + + template <class T> + inline T&& forward(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT + { + //"boost::forward<T> error: 'T' is a lvalue reference, can't forward as rvalue."; + BOOST_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value); + return static_cast<T&&>(t); + } + + #endif //BOOST_MOVE_DOXYGEN_INVOKED + + ////////////////////////////////////////////////////////////////////////////// + // + // move_if_not_lvalue_reference + // + ////////////////////////////////////////////////////////////////////////////// + + + #if defined(BOOST_MOVE_DOXYGEN_INVOKED) + template <class T> output_reference move_if_not_lvalue_reference(input_reference) noexcept; + #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) + + //Old move approach, lvalues could bind to rvalue references + + template <class T> + inline T&& move_if_not_lvalue_reference(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT + { return t; } + + #else //Old move + + template <class T> + inline T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT + { return static_cast<T&&>(t); } + + template <class T> + inline T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT + { + //"boost::forward<T> error: 'T' is a lvalue reference, can't forward as rvalue."; + BOOST_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value); + return static_cast<T&&>(t); + } + + #endif //BOOST_MOVE_DOXYGEN_INVOKED + + } //namespace boost { + + #endif //#if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE) + +#endif //BOOST_NO_CXX11_RVALUE_REFERENCES + +#if !defined(BOOST_MOVE_DOXYGEN_INVOKED) + +namespace boost{ +namespace move_detail{ + +template<class T> +void swap(T &a, T &b) +{ + T c((::boost::move(a))); + a = ::boost::move(b); + b = ::boost::move(c); +} + +template <typename T> +typename boost::move_detail::add_rvalue_reference<T>::type declval(); + +} //namespace move_detail{ +} //namespace boost{ + +#endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED) + + +#include <boost/move/detail/config_end.hpp> + +#endif //#ifndef BOOST_MOVE_MOVE_UTILITY_CORE_HPP |