diff --git a/include/boost/move/algorithm.hpp b/include/boost/move/algorithm.hpp new file mode 100644 index 0000000..bc6639f --- /dev/null +++ b/include/boost/move/algorithm.hpp @@ -0,0 +1,258 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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 + +#include +#include +#include + +#include //copy, copy_backward +#include //uninitialized_copy + +namespace boost { + +////////////////////////////////////////////////////////////////////////////// +// +// move +// +////////////////////////////////////////////////////////////////////////////// + +#if !defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE) + + //! Effects: 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)). + //! + //! Effects: result + (last - first). + //! + //! Requires: result shall not be in the range [first,last). + //! + //! Complexity: Exactly last - first move assignments. + template // O models OutputIterator + O move(I f, I l, O result) + { + while (f != l) { + *result = ::boost::move(*f); + ++f; ++result; + } + return result; + } + + ////////////////////////////////////////////////////////////////////////////// + // + // move_backward + // + ////////////////////////////////////////////////////////////////////////////// + + //! Effects: 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)). + //! + //! Requires: result shall not be in the range [first,last). + //! + //! Returns: result - (last - first). + //! + //! Complexity: Exactly last - first assignments. + template // 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 +// +////////////////////////////////////////////////////////////////////////////// + +//! Effects: +//! \code +//! for (; first != last; ++result, ++first) +//! new (static_cast(&*result)) +//! typename iterator_traits::value_type(boost::move(*first)); +//! \endcode +//! +//! Returns: result +template + // F models ForwardIterator +F uninitialized_move(I f, I l, F r + /// @cond +// ,typename ::boost::move_detail::enable_if::value_type> >::type* = 0 + /// @endcond + ) +{ + typedef typename std::iterator_traits::value_type input_value_type; + while (f != l) { + ::new(static_cast(&*r)) input_value_type(boost::move(*f)); + ++f; ++r; + } + return r; +} + +/// @cond +/* +template + // F models ForwardIterator +F uninitialized_move(I f, I l, F r, + typename ::boost::move_detail::disable_if::value_type> >::type* = 0) +{ + return std::uninitialized_copy(f, l, r); +} +*/ + +////////////////////////////////////////////////////////////////////////////// +// +// uninitialized_copy_or_move +// +////////////////////////////////////////////////////////////////////////////// + +namespace move_detail { + +template + // 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 >::type* = 0 +) +{ + return ::boost::uninitialized_move(f, l, r); +} +/* +template + // F models ForwardIterator +F uninitialized_move_move_iterator(I f, I l, F r, + typename ::boost::move_detail::disable_if< has_move_emulation_enabled >::type* = 0) +{ + return std::uninitialized_copy(f.base(), l.base(), r); +} +*/ +} //namespace move_detail { + +template + // 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 >::type* = 0) +{ + return ::boost::move_detail::uninitialized_move_move_iterator(f, l, r); +} + +////////////////////////////////////////////////////////////////////////////// +// +// copy_or_move +// +////////////////////////////////////////////////////////////////////////////// + +namespace move_detail { + +template + // F models ForwardIterator +inline F move_move_iterator(I f, I l, F r +// ,typename ::boost::move_detail::enable_if< has_move_emulation_enabled >::type* = 0 +) +{ + return ::boost::move(f, l, r); +} +/* +template + // F models ForwardIterator +F move_move_iterator(I f, I l, F r, + typename ::boost::move_detail::disable_if< has_move_emulation_enabled >::type* = 0) +{ + return std::copy(f.base(), l.base(), r); +} +*/ + +} //namespace move_detail { + +template + // 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 >::type* = 0) +{ + return ::boost::move_detail::move_move_iterator(f, l, r); +} + +/// @endcond + +//! Effects: +//! \code +//! for (; first != last; ++result, ++first) +//! new (static_cast(&*result)) +//! typename iterator_traits::value_type(*first); +//! \endcode +//! +//! Returns: result +//! +//! Note: This function is provided because +//! std::uninitialized_copy from some STL implementations +//! is not compatible with move_iterator +template + // 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 >::type* = 0 + /// @endcond + ) +{ + return std::uninitialized_copy(f, l, r); +} + +//! Effects: +//! \code +//! for (; first != last; ++result, ++first) +//! *result = *first; +//! \endcode +//! +//! Returns: result +//! +//! Note: This function is provided because +//! std::uninitialized_copy from some STL implementations +//! is not compatible with move_iterator +template + // 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 >::type* = 0 + /// @endcond + ) +{ + return std::copy(f, l, r); +} + +} //namespace boost { + +#include + +#endif //#ifndef BOOST_MOVE_MOVE_HPP diff --git a/include/boost/move/core.hpp b/include/boost/move/core.hpp new file mode 100644 index 0000000..2a11bad --- /dev/null +++ b/include/boost/move/core.hpp @@ -0,0 +1,309 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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 core.hpp +//! This header implements macros to define movable classes and +//! move-aware functions + +#ifndef BOOST_MOVE_CORE_HPP +#define BOOST_MOVE_CORE_HPP + +#include + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED) + + #include + + //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 { + + ////////////////////////////////////////////////////////////////////////////// + // + // struct rv + // + ////////////////////////////////////////////////////////////////////////////// + template + class rv + : public ::boost::move_detail::if_c + < ::boost::move_detail::is_class_or_union::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 + struct is_rv + : ::boost::move_detail::integral_constant + {}; + + template + struct is_rv< rv > + : ::boost::move_detail::integral_constant + {}; + + template + struct is_rv< const rv > + : ::boost::move_detail::integral_constant + {}; + + } //namespace move_detail { + + ////////////////////////////////////////////////////////////////////////////// + // + // has_move_emulation_enabled + // + ////////////////////////////////////////////////////////////////////////////// + template + struct has_move_emulation_enabled + : ::boost::move_detail::is_convertible< T, ::boost::rv& > + {}; + + template + struct has_move_emulation_enabled + : ::boost::move_detail::integral_constant + {}; + + template + struct has_move_emulation_enabled< ::boost::rv > + : ::boost::move_detail::integral_constant + {}; + + } //namespace boost { + + #define BOOST_RV_REF(TYPE)\ + ::boost::rv< TYPE >& \ + // + + #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ + ::boost::rv< TYPE >& \ + // + + #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ + ::boost::rv< TYPE >& \ + // + + #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 >& \ + // + + #define BOOST_MOVE_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ + const ::boost::rv< TYPE >& \ + // + + ////////////////////////////////////////////////////////////////////////////// + // + // BOOST_MOVABLE_BUT_NOT_COPYABLE + // + ////////////////////////////////////////////////////////////////////////////// + #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\ + private:\ + TYPE(TYPE &);\ + TYPE& operator=(TYPE &);\ + public:\ + operator ::boost::rv&() \ + { return *static_cast< ::boost::rv* >(this); }\ + operator const ::boost::rv&() const \ + { return *static_cast* >(this); }\ + private:\ + // + + ////////////////////////////////////////////////////////////////////////////// + // + // BOOST_COPYABLE_AND_MOVABLE + // + ////////////////////////////////////////////////////////////////////////////// + + #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\ + public:\ + TYPE& operator=(TYPE &t)\ + { this->operator=(static_cast &>(const_cast(t))); return *this;}\ + public:\ + operator ::boost::rv&() \ + { return *static_cast< ::boost::rv* >(this); }\ + operator const ::boost::rv&() const \ + { return *static_cast* >(this); }\ + private:\ + // + + #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\ + public:\ + operator ::boost::rv&() \ + { return *static_cast< ::boost::rv* >(this); }\ + operator const ::boost::rv&() const \ + { return *static_cast* >(this); }\ + private:\ + // + +#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 + //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 + + //! 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)\ + // + + #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) + #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\ + // + #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED) + + //!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 + struct has_move_emulation_enabled + { + static const bool value = false; + }; + + //!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-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 problems 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 && \ + // + + #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ + TYPE && \ + // + + #define BOOST_COPY_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ + const TYPE & \ + // + + #define BOOST_COPY_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ + TYPE& \ + // + + #define BOOST_CATCH_CONST_RLVALUE(TYPE)\ + const TYPE & \ + // + + /// @endcond + + #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED) + +#endif //BOOST_NO_CXX11_RVALUE_REFERENCES + +#include + +#endif //#ifndef BOOST_MOVE_CORE_HPP diff --git a/include/boost/move/detail/config_begin.hpp b/include/boost/move/detail/config_begin.hpp new file mode 100644 index 0000000..837ee12 --- /dev/null +++ b/include/boost/move/detail/config_begin.hpp @@ -0,0 +1,23 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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. +// +////////////////////////////////////////////////////////////////////////////// +#include + +#ifdef BOOST_MSVC + #ifndef _CRT_SECURE_NO_DEPRECATE + #define BOOST_MOVE_CRT_SECURE_NO_DEPRECATE + #define _CRT_SECURE_NO_DEPRECATE + #endif + #ifndef _SCL_SECURE_NO_WARNINGS + #define BOOST_MOVE_SCL_SECURE_NO_WARNINGS + #define _SCL_SECURE_NO_WARNINGS + #endif + #pragma warning (push) + #pragma warning (disable : 4996) // "function": was declared deprecated +#endif diff --git a/include/boost/move/detail/config_end.hpp b/include/boost/move/detail/config_end.hpp new file mode 100644 index 0000000..c43bce0 --- /dev/null +++ b/include/boost/move/detail/config_end.hpp @@ -0,0 +1,20 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#if defined BOOST_MSVC + #pragma warning (pop) + #ifdef BOOST_MOVE_DETAIL_CRT_SECURE_NO_DEPRECATE + #undef BOOST_MOVE_DETAIL_CRT_SECURE_NO_DEPRECATE + #undef _CRT_SECURE_NO_DEPRECATE + #endif + #ifndef BOOST_MOVE_SCL_SECURE_NO_WARNINGS + #undef BOOST_MOVE_SCL_SECURE_NO_WARNINGS + #undef _SCL_SECURE_NO_WARNINGS + #endif +#endif diff --git a/include/boost/move/detail/meta_utils.hpp b/include/boost/move/detail/meta_utils.hpp new file mode 100644 index 0000000..2bdb654 --- /dev/null +++ b/include/boost/move/detail/meta_utils.hpp @@ -0,0 +1,158 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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 + +//Small meta-typetraits to support move + +namespace boost { +namespace move_detail { + +//if_ +template +struct if_c +{ + typedef T1 type; +}; + +template +struct if_c +{ + typedef T2 type; +}; + +template +struct if_ +{ + typedef typename if_c<0 != T1::value, T2, T3>::type type; +}; + +//enable_if_ +template +struct enable_if_c +{ + typedef T type; +}; + +template +struct enable_if_c {}; + +template +struct enable_if : public enable_if_c {}; + +template +struct disable_if : public enable_if_c {}; + +//integral_constant +template +struct integral_constant +{ + static const T value = v; + typedef T value_type; + typedef integral_constant type; +}; + +//identity +template +struct identity +{ + typedef T type; +}; + +//is_convertible +template +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 > +struct and_ + : public integral_constant +{}; + +template +struct not_ + : public integral_constant +{}; + +//is_lvalue_reference +template +struct is_lvalue_reference + : public integral_constant +{}; + +template +struct is_lvalue_reference + : public integral_constant +{}; + +template +struct is_class_or_union +{ + struct twochar { char _[2]; }; + template + static char is_class_or_union_tester(void(U::*)(void)); + template + static twochar is_class_or_union_tester(...); + static const bool value = sizeof(is_class_or_union_tester(0)) == sizeof(char); +}; + +struct empty{}; + +//addressof +template 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 struct addressof_impl +{ + static inline T * f( T & v, long ) + { + return reinterpret_cast( + &const_cast(reinterpret_cast(v))); + } + + static inline T * f( T * v, int ) + { return v; } +}; + +template +inline T * addressof( T & v ) +{ + return ::boost::move_detail::addressof_impl::f + ( ::boost::move_detail::addr_impl_ref( v ), 0 ); +} + +} //namespace move_detail { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP diff --git a/include/boost/move/move_helpers.hpp b/include/boost/move/detail/move_helpers.hpp similarity index 93% rename from include/boost/move/move_helpers.hpp rename to include/boost/move/detail/move_helpers.hpp index eaf51d6..ddfea9b 100644 --- a/include/boost/move/move_helpers.hpp +++ b/include/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,19 +12,21 @@ #ifndef BOOST_MOVE_MOVE_HELPERS_HPP #define BOOST_MOVE_MOVE_HELPERS_HPP -#include +#include #include +#include +#include -#if defined(BOOST_NO_RVALUE_REFERENCES) || (defined(_MSC_VER) && (_MSC_VER == 1600)) +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || (defined(_MSC_VER) && (_MSC_VER == 1600)) #include #include #endif -#if defined(BOOST_NO_RVALUE_REFERENCES) +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) #include #endif -#if defined(BOOST_NO_RVALUE_REFERENCES) +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) struct not_a_type; #define BOOST_MOVE_CATCH_CONST(U) \ typename ::boost::mpl::if_< ::boost::is_class, BOOST_CATCH_CONST_RLVALUE(U), const U &>::type @@ -37,7 +39,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)\ @@ -104,7 +106,7 @@ 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)\ RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_CONST(TYPE) x)\ diff --git a/include/boost/move/iterator.hpp b/include/boost/move/iterator.hpp new file mode 100644 index 0000000..b4bc1af --- /dev/null +++ b/include/boost/move/iterator.hpp @@ -0,0 +1,298 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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 +#include +#include //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 move_iterator +{ + public: + typedef It iterator_type; + typedef typename std::iterator_traits::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 + , ::boost::rv& + , value_type & >::type reference; + #endif + typedef It pointer; + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename std::iterator_traits::iterator_category iterator_category; + + move_iterator() + {} + + explicit move_iterator(It i) + : m_it(i) + {} + + template + move_iterator(const move_iterator& 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 operator++(int) + { move_iterator tmp(*this); ++(*this); return tmp; } + + move_iterator& operator--() + { --m_it; return *this; } + + move_iterator operator--(int) + { move_iterator tmp(*this); --(*this); return tmp; } + + move_iterator operator+ (difference_type n) const + { return move_iterator(m_it + n); } + + move_iterator& operator+=(difference_type n) + { m_it += n; return *this; } + + move_iterator operator- (difference_type n) const + { return move_iterator(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 +struct is_move_iterator + : public ::boost::move_detail::integral_constant +{ +}; + +template +struct is_move_iterator< ::boost::move_iterator > + : public ::boost::move_detail::integral_constant +{ +}; + +} //namespace move_detail { + +////////////////////////////////////////////////////////////////////////////// +// +// move_iterator +// +////////////////////////////////////////////////////////////////////////////// + +//! +//! Returns: move_iterator(i). +template +inline move_iterator make_move_iterator(const It &it) +{ return move_iterator(it); } + +////////////////////////////////////////////////////////////////////////////// +// +// back_move_insert_iterator +// +////////////////////////////////////////////////////////////////////////////// + + +//! A move insert iterator that move constructs elements at the +//! back of a container +template // C models Container +class back_move_insert_iterator + : public std::iterator +{ + 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; } +}; + +//! +//! Returns: back_move_insert_iterator(x). +template // C models Container +inline back_move_insert_iterator back_move_inserter(C& x) +{ + return back_move_insert_iterator(x); +} + +////////////////////////////////////////////////////////////////////////////// +// +// front_move_insert_iterator +// +////////////////////////////////////////////////////////////////////////////// + +//! A move insert iterator that move constructs elements int the +//! front of a container +template // C models Container +class front_move_insert_iterator + : public std::iterator +{ + 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; } +}; + +//! +//! Returns: front_move_insert_iterator(x). +template // C models Container +inline front_move_insert_iterator front_move_inserter(C& x) +{ + return front_move_insert_iterator(x); +} + +////////////////////////////////////////////////////////////////////////////// +// +// insert_move_iterator +// +////////////////////////////////////////////////////////////////////////////// +template // C models Container +class move_insert_iterator + : public std::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; + + 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; } +}; + +//! +//! Returns: move_insert_iterator(x, it). +template // C models Container +inline move_insert_iterator move_inserter(C& x, typename C::iterator it) +{ + return move_insert_iterator(x, it); +} + +} //namespace boost { + +#include + +#endif //#ifndef BOOST_MOVE_ITERATOR_HPP diff --git a/include/boost/move/move.hpp b/include/boost/move/move.hpp index 6029d6d..66e99a7 100644 --- a/include/boost/move/move.hpp +++ b/include/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) @@ -10,1264 +10,18 @@ // ////////////////////////////////////////////////////////////////////////////// -//! \file +//! \file move.hpp +//! 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 - -#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 //copy, copy_backward -#include //uninitialized_copy -#include //std::iterator - -#define BOOST_MOVE_AVOID_BOOST_DEPENDENCIES - -//If boost dependencies are avoided include all machinery -#if !defined(BOOST_MOVE_AVOID_BOOST_DEPENDENCIES) - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - - #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 - struct if_c - { - typedef T1 type; - }; - - template - struct if_c - { - typedef T2 type; - }; - - template - struct if_ - { - typedef typename if_c<0 != T1::value, T2, T3>::type type; - }; - - //enable_if_ - template - struct enable_if_c - { - typedef T type; - }; - - template - struct enable_if_c {}; - - template - struct enable_if : public enable_if_c {}; - - template - struct disable_if : public enable_if_c {}; - - //integral_constant - template - struct integral_constant - { - static const T value = v; - typedef T value_type; - typedef integral_constant type; - }; - - //identity - template - struct identity - { - typedef T type; - }; - - //is_convertible - template - 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 > - struct and_ - : public integral_constant - {}; - - template - struct not_ - : public integral_constant - {}; - - //is_lvalue_reference - template - struct is_lvalue_reference - : public integral_constant - {}; - - template - struct is_lvalue_reference - : public integral_constant - {}; - - //has_trivial_destructor - template - struct has_trivial_destructor - : public integral_constant - {}; - - //addressof - template 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 struct addressof_impl - { - static inline T * f( T & v, long ) - { - return reinterpret_cast( - &const_cast(reinterpret_cast(v))); - } - - static inline T * f( T * v, int ) - { return v; } - }; - - template - inline T * addressof( T & v ) - { - return ::boost::move_detail::addressof_impl::f - ( ::boost::move_detail::addr_impl_ref( 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 - struct is_class_or_union - { - struct twochar { char _[2]; }; - template - static char is_class_or_union_tester(void(U::*)(void)); - template - static twochar is_class_or_union_tester(...); - static const bool value = sizeof(is_class_or_union_tester(0)) == sizeof(char); - }; - struct empty{}; - } - - ////////////////////////////////////////////////////////////////////////////// - // - // struct rv - // - ////////////////////////////////////////////////////////////////////////////// - template - class rv - : public BOOST_MOVE_MPL_NS::if_c - < ::boost::move_detail::is_class_or_union::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 - struct is_rv - : BOOST_MOVE_BOOST_NS::integral_constant - {}; - - template - struct is_rv< rv > - : BOOST_MOVE_BOOST_NS::integral_constant - {}; - - template - struct is_rv< const rv > - : BOOST_MOVE_BOOST_NS::integral_constant - {}; - - } //namespace move_detail { - - ////////////////////////////////////////////////////////////////////////////// - // - // has_move_emulation_enabled - // - ////////////////////////////////////////////////////////////////////////////// - template - struct has_move_emulation_enabled - : BOOST_MOVE_BOOST_NS::is_convertible< T, ::boost::rv& > - {}; - - template - struct has_move_emulation_enabled - : BOOST_MOVE_BOOST_NS::integral_constant - {}; - - template - struct has_move_emulation_enabled< ::boost::rv > - : BOOST_MOVE_BOOST_NS::integral_constant - {}; - - template - struct has_move_emulation_enabled_aux - : has_move_emulation_enabled {}; - - template - struct has_nothrow_move - : public BOOST_MOVE_BOOST_NS::integral_constant - {}; - - ////////////////////////////////////////////////////////////////////////////// - // - // move() - // - ////////////////////////////////////////////////////////////////////////////// - - template - inline typename BOOST_MOVE_BOOST_NS::disable_if, T&>::type move(T& x) - { - return x; - } - - template - inline typename BOOST_MOVE_BOOST_NS::enable_if, rv&>::type move(T& x) - { - return *static_cast* >(BOOST_MOVE_BOOST_NS::addressof(x)); - } - - template - inline typename BOOST_MOVE_BOOST_NS::enable_if, rv&>::type move(rv& x) - { - return x; - } - - #define BOOST_RV_REF(TYPE)\ - ::boost::rv< TYPE >& \ - // - - #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ - ::boost::rv< TYPE >& \ - // - - #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ - ::boost::rv< TYPE >& \ - // - - #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 >& \ - // - - #define BOOST_MOVE_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ - const ::boost::rv< TYPE >& \ - // - - ////////////////////////////////////////////////////////////////////////////// - // - // forward() - // - ////////////////////////////////////////////////////////////////////////////// - - template - inline typename BOOST_MOVE_BOOST_NS::enable_if< ::boost::move_detail::is_rv, T &>::type - forward(const typename BOOST_MOVE_MPL_NS::identity::type &x) - { - return const_cast(x); - } - - template - inline typename BOOST_MOVE_BOOST_NS::disable_if< ::boost::move_detail::is_rv, const T &>::type - forward(const typename BOOST_MOVE_MPL_NS::identity::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&() \ - { return *static_cast< ::boost::rv* >(this); }\ - operator const ::boost::rv&() const \ - { return *static_cast* >(this); }\ - private:\ - // - - ////////////////////////////////////////////////////////////////////////////// - // - // BOOST_COPYABLE_AND_MOVABLE - // - ////////////////////////////////////////////////////////////////////////////// - - #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\ - public:\ - TYPE& operator=(TYPE &t)\ - { this->operator=(static_cast &>(const_cast(t))); return *this;}\ - public:\ - operator ::boost::rv&() \ - { return *static_cast< ::boost::rv* >(this); }\ - operator const ::boost::rv&() const \ - { return *static_cast* >(this); }\ - private:\ - // - - #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\ - public:\ - operator ::boost::rv&() \ - { return *static_cast< ::boost::rv* >(this); }\ - operator const ::boost::rv&() const \ - { return *static_cast* >(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 - struct has_nothrow_move - : public BOOST_MOVE_MPL_NS::integral_constant - {}; - - } // namespace boost{ - - #if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE) - #include - - namespace boost{ - - using ::std::move; - using ::std::forward; - using ::std::move_backward; - - } //namespace boost - - #else //!BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE - - #include - - 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 - //! ::boost::rv & so that move emulation is activated. - template - rvalue_reference move (input_reference); - - #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) - - //Old move approach, lvalues could bind to rvalue references - template - inline typename remove_reference::type && move(T&& t) - { return t; } - - #else //Old move - - template - inline typename remove_reference::type && move(T&& t) - { return static_cast::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 & then it output_reference is - //! ::boost::rev & - //! - //! * Else, input_reference is equal to output_reference is equal to input_reference. - template output_reference forward(input_reference); - #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) - - //Old move approach, lvalues could bind to rvalue references - - template - inline T&& forward (typename BOOST_MOVE_MPL_NS::identity::type&& t) - { return t; } - - #else //Old move - - //Implementation #5 from N2951, thanks to Howard Hinnant - - template - inline T&& forward(U&& t - , typename BOOST_MOVE_BOOST_NS::enable_if_c< - move_detail::is_lvalue_reference::value ? move_detail::is_lvalue_reference::value : true>::type * = 0/* - , typename BOOST_MOVE_BOOST_NS::enable_if_c< - move_detail::is_convertible - ::type*, typename remove_reference::type*>::value>::type * = 0*/) - { return static_cast(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 && \ - // - - #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ - TYPE && \ - // - - #define BOOST_COPY_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ - const TYPE & \ - // - - #define BOOST_COPY_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ - TYPE& \ - // - - #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 move_iterator -{ - public: - typedef It iterator_type; - typedef typename std::iterator_traits::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 - , ::boost::rv& - , value_type & >::type reference; - #endif - typedef It pointer; - typedef typename std::iterator_traits::difference_type difference_type; - typedef typename std::iterator_traits::iterator_category iterator_category; - - move_iterator() - {} - - explicit move_iterator(It i) - : m_it(i) - {} - - template - move_iterator(const move_iterator& 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 operator++(int) - { move_iterator tmp(*this); ++(*this); return tmp; } - - move_iterator& operator--() - { --m_it; return *this; } - - move_iterator operator--(int) - { move_iterator tmp(*this); --(*this); return tmp; } - - move_iterator operator+ (difference_type n) const - { return move_iterator(m_it + n); } - - move_iterator& operator+=(difference_type n) - { m_it += n; return *this; } - - move_iterator operator- (difference_type n) const - { return move_iterator(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 -struct is_move_iterator - : public BOOST_MOVE_BOOST_NS::integral_constant -{ -}; - -template -struct is_move_iterator< ::boost::move_iterator > - : public BOOST_MOVE_BOOST_NS::integral_constant -{ -}; - -} //namespace move_detail { - -////////////////////////////////////////////////////////////////////////////// -// -// move_iterator -// -////////////////////////////////////////////////////////////////////////////// - -//! -//! Returns: move_iterator(i). -template -inline move_iterator make_move_iterator(const It &it) -{ return move_iterator(it); } - -////////////////////////////////////////////////////////////////////////////// -// -// back_move_insert_iterator -// -////////////////////////////////////////////////////////////////////////////// - - -//! A move insert iterator that move constructs elements at the -//! back of a container -template // C models Container -class back_move_insert_iterator - : public std::iterator -{ - 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; } -}; - -//! -//! Returns: back_move_insert_iterator(x). -template // C models Container -inline back_move_insert_iterator back_move_inserter(C& x) -{ - return back_move_insert_iterator(x); -} - -////////////////////////////////////////////////////////////////////////////// -// -// front_move_insert_iterator -// -////////////////////////////////////////////////////////////////////////////// - -//! A move insert iterator that move constructs elements int the -//! front of a container -template // C models Container -class front_move_insert_iterator - : public std::iterator -{ - 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; } -}; - -//! -//! Returns: front_move_insert_iterator(x). -template // C models Container -inline front_move_insert_iterator front_move_inserter(C& x) -{ - return front_move_insert_iterator(x); -} - -////////////////////////////////////////////////////////////////////////////// -// -// insert_move_iterator -// -////////////////////////////////////////////////////////////////////////////// -template // C models Container -class move_insert_iterator - : public std::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; - - 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; } -}; - -//! -//! Returns: move_insert_iterator(x, it). -template // C models Container -inline move_insert_iterator move_inserter(C& x, typename C::iterator it) -{ - return move_insert_iterator(x, it); -} - -////////////////////////////////////////////////////////////////////////////// -// -// move -// -////////////////////////////////////////////////////////////////////////////// - -#if !defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE) - - //! Effects: 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)). - //! - //! Effects: result + (last - first). - //! - //! Requires: result shall not be in the range [first,last). - //! - //! Complexity: Exactly last - first move assignments. - template // O models OutputIterator - O move(I f, I l, O result) - { - while (f != l) { - *result = ::boost::move(*f); - ++f; ++result; - } - return result; - } - - ////////////////////////////////////////////////////////////////////////////// - // - // move_backward - // - ////////////////////////////////////////////////////////////////////////////// - - //! Effects: 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)). - //! - //! Requires: result shall not be in the range [first,last). - //! - //! Returns: result - (last - first). - //! - //! Complexity: Exactly last - first assignments. - template // 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 -// -////////////////////////////////////////////////////////////////////////////// - -//! Effects: -//! \code -//! for (; first != last; ++result, ++first) -//! new (static_cast(&*result)) -//! typename iterator_traits::value_type(boost::move(*first)); -//! \endcode -//! -//! Returns: result -template - // F models ForwardIterator -F uninitialized_move(I f, I l, F r - /// @cond -// ,typename BOOST_MOVE_BOOST_NS::enable_if::value_type> >::type* = 0 - /// @endcond - ) -{ - typedef typename std::iterator_traits::value_type input_value_type; - while (f != l) { - ::new(static_cast(&*r)) input_value_type(boost::move(*f)); - ++f; ++r; - } - return r; -} - -/// @cond -/* -template - // F models ForwardIterator -F uninitialized_move(I f, I l, F r, - typename BOOST_MOVE_BOOST_NS::disable_if::value_type> >::type* = 0) -{ - return std::uninitialized_copy(f, l, r); -} -*/ - -////////////////////////////////////////////////////////////////////////////// -// -// uninitialized_copy_or_move -// -////////////////////////////////////////////////////////////////////////////// - -namespace move_detail { - -template - // 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 >::type* = 0 -) -{ - return ::boost::uninitialized_move(f, l, r); -} -/* -template - // 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 >::type* = 0) -{ - return std::uninitialized_copy(f.base(), l.base(), r); -} -*/ -} //namespace move_detail { - -template - // 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 >::type* = 0) -{ - return ::boost::move_detail::uninitialized_move_move_iterator(f, l, r); -} - -////////////////////////////////////////////////////////////////////////////// -// -// copy_or_move -// -////////////////////////////////////////////////////////////////////////////// - -namespace move_detail { - -template - // 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 >::type* = 0 -) -{ - return ::boost::move(f, l, r); -} -/* -template - // F models ForwardIterator -F move_move_iterator(I f, I l, F r, - typename BOOST_MOVE_BOOST_NS::disable_if< has_move_emulation_enabled >::type* = 0) -{ - return std::copy(f.base(), l.base(), r); -} -*/ - -} //namespace move_detail { - -template - // 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 >::type* = 0) -{ - return ::boost::move_detail::move_move_iterator(f, l, r); -} - -/// @endcond - -//! Effects: -//! \code -//! for (; first != last; ++result, ++first) -//! new (static_cast(&*result)) -//! typename iterator_traits::value_type(*first); -//! \endcode -//! -//! Returns: result -//! -//! Note: This function is provided because -//! std::uninitialized_copy from some STL implementations -//! is not compatible with move_iterator -template - // 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 >::type* = 0 - /// @endcond - ) -{ - return std::uninitialized_copy(f, l, r); -} - -//! Effects: -//! \code -//! for (; first != last; ++result, ++first) -//! *result = *first; -//! \endcode -//! -//! Returns: result -//! -//! Note: This function is provided because -//! std::uninitialized_copy from some STL implementations -//! is not compatible with move_iterator -template - // 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 >::type* = 0 - /// @endcond - ) -{ - return std::copy(f, l, r); -} - -//! If this trait yields to true -//! (has_trivial_destructor_after_move <T>::value == true) -//! 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 -struct has_trivial_destructor_after_move - : BOOST_MOVE_BOOST_NS::has_trivial_destructor -{}; - - - -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 > - { 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 { }; -#ifndef BOOST_NO_RVALUE_REFERENCES - template< class T > struct is_rvalue_reference< T&& > : BOOST_MOVE_BOOST_NS::integral_constant { }; -#else // #ifndef BOOST_NO_RVALUE_REFERENCES - template< class T > struct is_rvalue_reference< boost::rv& > - : BOOST_MOVE_BOOST_NS::integral_constant - {}; - - template< class T > struct is_rvalue_reference< const boost::rv& > - : BOOST_MOVE_BOOST_NS::integral_constant - {}; -#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::value - , bool rv = ::boost::move_detail::is_rv::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& type; }; - } // namespace detail_add_rvalue_reference - - template< class T > - struct add_rvalue_reference - : detail_add_rvalue_reference::add_rvalue_reference_impl - { }; - - template< class T > - struct add_rvalue_reference - { 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 > { typedef T type; }; - template< class T > struct remove_rvalue_reference< const rv > { typedef T type; }; - template< class T > struct remove_rvalue_reference< volatile rv > { typedef T type; }; - template< class T > struct remove_rvalue_reference< const volatile rv > { typedef T type; }; - template< class T > struct remove_rvalue_reference< rv& > { typedef T type; }; - template< class T > struct remove_rvalue_reference< const rv& > { typedef T type; }; - template< class T > struct remove_rvalue_reference< volatile rv& > { typedef T type; }; - template< class T > struct remove_rvalue_reference< const volatile rv& >{ typedef T type; }; -#endif // #ifndef BOOST_NO_RVALUE_REFERENCES - -template -typename boost::move_detail::add_rvalue_reference::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& rather than -// rv& (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 +#include +#include +#include +#include +#include #endif //#ifndef BOOST_MOVE_MOVE_HPP diff --git a/include/boost/move/traits.hpp b/include/boost/move/traits.hpp new file mode 100644 index 0000000..e5c8444 --- /dev/null +++ b/include/boost/move/traits.hpp @@ -0,0 +1,142 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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 +#include +#include + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#include +#endif + +namespace boost { + +//! If this trait yields to true +//! (has_trivial_destructor_after_move <T>::value == true) +//! 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 +struct has_trivial_destructor_after_move + : ::boost::has_trivial_destructor +{}; + +//! By default this traits returns false. Classes with non-throwing move constructor +//! and assignment can specialize this trait to obtain some performance improvements. +template +struct has_nothrow_move + : public ::boost::move_detail::integral_constant +{}; + +namespace move_detail { + +// Code from Jeffrey Lee Hellrung, many thanks + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template< class T> struct forward_type { typedef T type; }; +#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template< class T> + struct forward_type + { typedef const T &type; }; + + template< class T> + struct forward_type< boost::rv > + { typedef T type; }; +#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +template< class T > struct is_rvalue_reference : ::boost::move_detail::integral_constant { }; +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template< class T > struct is_rvalue_reference< T&& > : ::boost::move_detail::integral_constant { }; +#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template< class T > struct is_rvalue_reference< boost::rv& > + : ::boost::move_detail::integral_constant + {}; + + template< class T > struct is_rvalue_reference< const boost::rv& > + : ::boost::move_detail::integral_constant + {}; +#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 = ::boost::has_move_emulation_enabled::value + , bool rv = ::boost::move_detail::is_rv::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& type; }; + } // namespace detail_add_rvalue_reference + + template< class T > + struct add_rvalue_reference + : detail_add_rvalue_reference::add_rvalue_reference_impl + { }; + + template< class T > + struct add_rvalue_reference + { 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 > { typedef T type; }; + template< class T > struct remove_rvalue_reference< const rv > { typedef T type; }; + template< class T > struct remove_rvalue_reference< volatile rv > { typedef T type; }; + template< class T > struct remove_rvalue_reference< const volatile rv > { typedef T type; }; + template< class T > struct remove_rvalue_reference< rv& > { typedef T type; }; + template< class T > struct remove_rvalue_reference< const rv& > { typedef T type; }; + template< class T > struct remove_rvalue_reference< volatile rv& > { typedef T type; }; + template< class T > struct remove_rvalue_reference< const volatile rv& >{ typedef T type; }; +#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +template +typename boost::move_detail::add_rvalue_reference::type declval(); + +} //move_detail { + +// 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& rather than +// rv& (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 { + +#include + +#endif //#ifndef BOOST_MOVE_MOVE_TRAITS_HPP diff --git a/include/boost/move/utility.hpp b/include/boost/move/utility.hpp new file mode 100644 index 0000000..fb2ec69 --- /dev/null +++ b/include/boost/move/utility.hpp @@ -0,0 +1,194 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_MOVE_UTILITY_HPP +#define BOOST_MOVE_MOVE_UTILITY_HPP + +#include +#include +#include + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED) + + namespace boost { + + template + struct enable_move_utility_emulation + { + static const bool value = true; + }; + + ////////////////////////////////////////////////////////////////////////////// + // + // move() + // + ////////////////////////////////////////////////////////////////////////////// + + template + inline typename ::boost::move_detail::enable_if_c + < enable_move_utility_emulation::value && !has_move_emulation_enabled::value, T&>::type + move(T& x) + { + return x; + } + + template + inline typename ::boost::move_detail::enable_if_c + < enable_move_utility_emulation::value && has_move_emulation_enabled::value, rv&>::type + move(T& x) + { + return *static_cast* >(::boost::move_detail::addressof(x)); + } + + template + inline typename ::boost::move_detail::enable_if_c + < enable_move_utility_emulation::value && has_move_emulation_enabled::value, rv&>::type + move(rv& x) + { + return x; + } + + ////////////////////////////////////////////////////////////////////////////// + // + // forward() + // + ////////////////////////////////////////////////////////////////////////////// + + template + inline typename ::boost::move_detail::enable_if_c + < enable_move_utility_emulation::value && ::boost::move_detail::is_rv::value, T &>::type + forward(const typename ::boost::move_detail::identity::type &x) + { + return const_cast(x); + } + + template + inline typename ::boost::move_detail::enable_if_c + < enable_move_utility_emulation::value && !::boost::move_detail::is_rv::value, const T &>::type + forward(const typename ::boost::move_detail::identity::type &x) + { + 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 + + namespace boost{ + + using ::std::move; + using ::std::forward; + + } //namespace boost + + #else //!BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE + + #include + + 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 + 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 converts T & into + //! ::boost::rv & so that move emulation is activated. + template + rvalue_reference move (input_reference); + + #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) + + //Old move approach, lvalues could bind to rvalue references + template + inline typename remove_reference::type && move(T&& t) + { return t; } + + #else //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES + + template + inline typename remove_reference::type && move(T&& t) + { return static_cast::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 & then it output_reference is + //! ::boost::rv & + //! + //! * Else, output_reference is equal to input_reference. + template output_reference forward(input_reference); + #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) + + //Old move approach, lvalues could bind to rvalue references + + template + inline T&& forward (typename ::boost::move_detail::identity::type&& t) + { return t; } + + #else //Old move + + //Implementation #5 from N2951, thanks to Howard Hinnant + + template + inline T&& forward(U&& t + , typename ::boost::move_detail::enable_if_c< + move_detail::is_lvalue_reference::value ? move_detail::is_lvalue_reference::value : true>::type * = 0/* + , typename ::boost::move_detail::enable_if_c< + move_detail::is_convertible + ::type*, typename remove_reference::type*>::value>::type * = 0*/) + { return static_cast(t); } + + #endif //BOOST_MOVE_DOXYGEN_INVOKED + + } //namespace boost { + + #endif //#if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE) + +#endif //BOOST_NO_CXX11_RVALUE_REFERENCES + +#include + +#endif //#ifndef BOOST_MOVE_MOVE_UTILITY_HPP