From 88da98e37b9539c103ae9e6fc7db1b4e52010585 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 31 Jul 2007 20:32:15 +0000 Subject: [PATCH 1/8] Move top-level boost directory over to "devel" (temporarily) [SVN r38327] --- .gitattributes | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3e84d7c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,96 @@ +* text=auto !eol svneol=native#text/plain +*.gitattributes text svneol=native#text/plain + +# Scriptish formats +*.bat text svneol=native#text/plain +*.bsh text svneol=native#text/x-beanshell +*.cgi text svneol=native#text/plain +*.cmd text svneol=native#text/plain +*.js text svneol=native#text/javascript +*.php text svneol=native#text/x-php +*.pl text svneol=native#text/x-perl +*.pm text svneol=native#text/x-perl +*.py text svneol=native#text/x-python +*.sh eol=lf svneol=LF#text/x-sh +configure eol=lf svneol=LF#text/x-sh + +# Image formats +*.bmp binary svneol=unset#image/bmp +*.gif binary svneol=unset#image/gif +*.ico binary svneol=unset#image/ico +*.jpeg binary svneol=unset#image/jpeg +*.jpg binary svneol=unset#image/jpeg +*.png binary svneol=unset#image/png +*.tif binary svneol=unset#image/tiff +*.tiff binary svneol=unset#image/tiff +*.svg text svneol=native#image/svg%2Bxml + +# Data formats +*.pdf binary svneol=unset#application/pdf +*.avi binary svneol=unset#video/avi +*.doc binary svneol=unset#application/msword +*.dsp text svneol=crlf#text/plain +*.dsw text svneol=crlf#text/plain +*.eps binary svneol=unset#application/postscript +*.gz binary svneol=unset#application/gzip +*.mov binary svneol=unset#video/quicktime +*.mp3 binary svneol=unset#audio/mpeg +*.ppt binary svneol=unset#application/vnd.ms-powerpoint +*.ps binary svneol=unset#application/postscript +*.psd binary svneol=unset#application/photoshop +*.rdf binary svneol=unset#text/rdf +*.rss text svneol=unset#text/xml +*.rtf binary svneol=unset#text/rtf +*.sln text svneol=native#text/plain +*.swf binary svneol=unset#application/x-shockwave-flash +*.tgz binary svneol=unset#application/gzip +*.vcproj text svneol=native#text/xml +*.vcxproj text svneol=native#text/xml +*.vsprops text svneol=native#text/xml +*.wav binary svneol=unset#audio/wav +*.xls binary svneol=unset#application/vnd.ms-excel +*.zip binary svneol=unset#application/zip + +# Text formats +.htaccess text svneol=native#text/plain +*.bbk text svneol=native#text/xml +*.cmake text svneol=native#text/plain +*.css text svneol=native#text/css +*.dtd text svneol=native#text/xml +*.htm text svneol=native#text/html +*.html text svneol=native#text/html +*.ini text svneol=native#text/plain +*.log text svneol=native#text/plain +*.mak text svneol=native#text/plain +*.qbk text svneol=native#text/plain +*.rst text svneol=native#text/plain +*.sql text svneol=native#text/x-sql +*.txt text svneol=native#text/plain +*.xhtml text svneol=native#text/xhtml%2Bxml +*.xml text svneol=native#text/xml +*.xsd text svneol=native#text/xml +*.xsl text svneol=native#text/xml +*.xslt text svneol=native#text/xml +*.xul text svneol=native#text/xul +*.yml text svneol=native#text/plain +boost-no-inspect text svneol=native#text/plain +CHANGES text svneol=native#text/plain +COPYING text svneol=native#text/plain +INSTALL text svneol=native#text/plain +Jamfile text svneol=native#text/plain +Jamroot text svneol=native#text/plain +Jamfile.v2 text svneol=native#text/plain +Jamrules text svneol=native#text/plain +Makefile* text svneol=native#text/plain +README text svneol=native#text/plain +TODO text svneol=native#text/plain + +# Code formats +*.c text svneol=native#text/plain +*.cpp text svneol=native#text/plain +*.h text svneol=native#text/plain +*.hpp text svneol=native#text/plain +*.ipp text svneol=native#text/plain +*.tpp text svneol=native#text/plain +*.jam text svneol=native#text/plain +*.java text svneol=native#text/plain From 3362ca85e609d2f3def17a4c0c61df14a2fdc705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 17 Mar 2011 16:12:07 +0000 Subject: [PATCH 2/8] Added to trunk [SVN r70062] --- include/boost/move/move.hpp | 1099 +++++++++++++++++++++++++++ include/boost/move/move_helpers.hpp | 173 +++++ 2 files changed, 1272 insertions(+) create mode 100644 include/boost/move/move.hpp create mode 100644 include/boost/move/move_helpers.hpp diff --git a/include/boost/move/move.hpp b/include/boost/move/move.hpp new file mode 100644 index 0000000..bc1be1e --- /dev/null +++ b/include/boost/move/move.hpp @@ -0,0 +1,1099 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright David Abrahams, Vicente Botet 2009. +// (C) Copyright Ion Gaztanaga 2009-2010. +// 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_HPP +#define BOOST_MOVE_MOVE_HPP + +#include +#include //copy, copy_backward +#include //uninitialized_copy +#include //std::iterator + +#define BOOST_MOVE_AVOID_BOOST_DEPENDENCIES + +#ifndef BOOST_MOVE_AVOID_BOOST_DEPENDENCIES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif //#ifdef BOOST_MOVE_AVOID_BOOST_DEPENDENCIES +/// @cond + +#ifdef BOOST_MOVE_AVOID_BOOST_DEPENDENCIES +#define BOOST_MOVE_MPL_NS ::boost::move_detail +#define BOOST_MOVE_BOOST_NS ::boost::move_detail +#else +#define BOOST_MOVE_MPL_NS ::boost::mpl +#define BOOST_MOVE_BOOST_NS ::boost +#endif + +#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 T * addressof( T & v ) +{ + return ::boost::move_detail::addressof_impl::f + ( ::boost::move_detail::addr_impl_ref( v ), 0 ); +} + +/* +typedef char one; +struct two {one _[2];}; + +template +struct is_base_of_host +{ + operator B*() const; + operator D*(); +}; + +template +struct is_base_of +{ + typedef char yes; + class no { char dummy[2]; }; + + template + static yes check(D*, T); + static no check(B*, int); + + static const bool value = sizeof(check(is_base_of_host(), int())) == sizeof(yes); +}; +*/ + +} //namespace move_detail { +} //namespace boost { + +#endif //BOOST_MOVE_AVOID_BOOST_DEPENDENCIES + +/// @endcond + +#if !defined(BOOST_NO_RVALUE_REFERENCES) + +#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 5) + +#define BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES + +#else + +#if defined(_MSC_VER) && (_MSC_VER == 1600) +#define BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG +#endif + +#endif + +#endif + + +#if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED) + +#ifdef __GNUC__ +# 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 T +{ + 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_nothrow_move + : public BOOST_MOVE_BOOST_NS::integral_constant +{}; + +////////////////////////////////////////////////////////////////////////////// +// +// move() +// +////////////////////////////////////////////////////////////////////////////// +template +typename BOOST_MOVE_BOOST_NS::disable_if, T&>::type move(T& x) +{ + return x; +} + +template +typename BOOST_MOVE_BOOST_NS::enable_if, rv&>::type move(T& x) +{ + return *static_cast* >(BOOST_MOVE_BOOST_NS::addressof(x)); +} + +template +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_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_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 +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 +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 + +#include + +namespace boost { + +//! By default this traits returns false. Classes with non-thworing move construction +//! and assignment should specialize this trait to obtain some performance improvements. +template +struct has_nothrow_move + : public BOOST_MOVE_MPL_NS::integral_constant +{}; + +////////////////////////////////////////////////////////////////////////////// +// +// 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 inline +rvalue_reference move (input_reference); + +#else //BOOST_MOVE_DOXYGEN_INVOKED + +#if 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 + +#endif //BOOST_MOVE_DOXYGEN_INVOKED + + +////////////////////////////////////////////////////////////////////////////// +// +// 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 inline output_reference forward(input_reference); + +#else + +#if 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 //Old move + +#endif //BOOST_MOVE_DOXYGEN_INVOKED + +////////////////////////////////////////////////////////////////////////////// +// +// BOOST_ENABLE_MOVE_EMULATION +// +////////////////////////////////////////////////////////////////////////////// + +///@cond + +#define BOOST_ENABLE_MOVE_EMULATION(TYPE)\ + typedef int boost_move_emulation_t; +\ +// + +/// @endcond + +//! 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)\ +// + +/// @cond + +#define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ + TYPE && \ +// + +#define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ + TYPE && \ +// + +/// @endcond + +//!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 copy +//!assignment for classes marked as BOOST_COPYABLE_AND_MOVABLE. +#define BOOST_COPY_ASSIGN_REF(TYPE)\ + const TYPE & \ +// + +/// @cond + +#define BOOST_COPY_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ + const TYPE & \ +// + +#define BOOST_COPY_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ + TYPE& \ +// + +/// @endcond + +//! This macro is used to implement portable perfect forwarding +//! as explained in the documentation. +#define BOOST_FWD_REF(TYPE)\ + TYPE && \ +// + +/// @cond + +#define BOOST_CATCH_CONST_RLVALUE(TYPE)\ + const TYPE & \ +// + +/// @endcond + +} //namespace boost { + +#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_MPL_NS::integral_constant +{ +}; + +template +struct is_move_iterator< ::boost::move_iterator > + : public BOOST_MOVE_MPL_NS::integral_constant +{ +}; + +} //namespace move_detail { + +////////////////////////////////////////////////////////////////////////////// +// +// move_iterator +// +////////////////////////////////////////////////////////////////////////////// + +//! +//! Returns: move_iterator(i). +template +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; + + explicit back_move_insert_iterator(C& x) : container_m(&x) { } + + back_move_insert_iterator& operator=(typename C::reference x) + { container_m->push_back(boost::move(x)); return *this; } + + 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; + + explicit front_move_insert_iterator(C& x) : container_m(&x) { } + + front_move_insert_iterator& operator=(typename C::reference x) + { container_m->push_front(boost::move(x)); return *this; } + + 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; + + explicit move_insert_iterator(C& x, typename C::iterator pos) + : container_m(&x), pos_(pos) + {} + + move_insert_iterator& operator=(typename C::reference x) + { + pos_ = container_m->insert(pos_, ::boost::move(x)); + ++pos_; + return *this; + } + + 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 +// +////////////////////////////////////////////////////////////////////////////// + + +//! 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; +} + +////////////////////////////////////////////////////////////////////////////// +// +// 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 +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 +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 +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 +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 +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 +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 boost { + +#endif //#ifndef BOOST_MOVE_MOVE_HPP diff --git a/include/boost/move/move_helpers.hpp b/include/boost/move/move_helpers.hpp new file mode 100644 index 0000000..92e052e --- /dev/null +++ b/include/boost/move/move_helpers.hpp @@ -0,0 +1,173 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2010-2011. +// 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_MOVE_HELPERS_HPP +#define BOOST_MOVE_MOVE_HELPERS_HPP + +#include +#include + +#if defined(BOOST_NO_RVALUE_REFERENCES) || (defined(_MSC_VER) && (_MSC_VER == 1600)) +#include +#include +#endif +#if defined(BOOST_NO_RVALUE_REFERENCES) +#include +#endif + + +#if defined(BOOST_NO_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 +#define BOOST_MOVE_CATCH_RVALUE(U)\ + typename ::boost::mpl::if_< ::boost::is_class, BOOST_RV_REF(T), not_a_type>::type +#define BOOST_MOVE_CATCH_FWD(U) BOOST_FWD_REF(U) +#else +#define BOOST_MOVE_CATCH_CONST(U) const U & +#define BOOST_MOVE_CATCH_RVALUE(U) U && +#define BOOST_MOVE_CATCH_FWD(U) U && +#endif + +#ifdef BOOST_NO_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(x)); }\ +\ + RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_RVALUE(TYPE) x) \ + { return FWD_FUNCTION(::boost::move(x)); }\ +\ + RETURN_VALUE PUB_FUNCTION(TYPE &x)\ + { return FWD_FUNCTION(const_cast(x)); }\ +\ + template\ + typename ::boost::enable_if_c\ + < ::boost::is_class::value &&\ + ::boost::is_same::value &&\ + !::boost::has_move_emulation_enabled::value\ + , RETURN_VALUE >::type\ + PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u)\ + { return FWD_FUNCTION(u); }\ +\ + template\ + typename ::boost::enable_if_c\ + < ::boost::is_class::value &&\ + !::boost::is_same::value &&\ + !::boost::move_detail::is_rv::value\ + , RETURN_VALUE >::type\ + PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u)\ + {\ + TYPE t(u);\ + return FWD_FUNCTION(::boost::move(t));\ + }\ +// + +#elif (defined(_MSC_VER) && (_MSC_VER == 1600)) + +#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(x)); }\ +\ + RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_RVALUE(TYPE) x) \ + { return FWD_FUNCTION(::boost::move(x)); }\ +\ + template\ + typename ::boost::enable_if_c\ + < !::boost::is_same::value\ + , RETURN_VALUE >::type\ + PUB_FUNCTION(const BOOST_MOVE_TEMPL_PARAM &u)\ + {\ + TYPE t(u);\ + return FWD_FUNCTION(::boost::move(t));\ + }\ +// + +#else + +#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(x)); }\ +\ + RETURN_VALUE PUB_FUNCTION(BOOST_MOVE_CATCH_RVALUE(TYPE) x) \ + { return FWD_FUNCTION(::boost::move(x)); }\ +// + +#endif + + +#ifdef BOOST_NO_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)\ + { return FWD_FUNCTION(arg1, static_cast(x)); }\ +\ + RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_RVALUE(TYPE) x) \ + { return FWD_FUNCTION(arg1, ::boost::move(x)); }\ +\ + RETURN_VALUE PUB_FUNCTION(ARG1 arg1, TYPE &x)\ + { return FWD_FUNCTION(arg1, const_cast(x)); }\ +\ + template\ + typename ::boost::enable_if_c\ + < ::boost::is_class::value &&\ + ::boost::is_same::value &&\ + !::boost::has_move_emulation_enabled::value\ + , RETURN_VALUE >::type\ + PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u)\ + { return FWD_FUNCTION(arg1, u); }\ +\ + template\ + typename ::boost::enable_if_c\ + < ::boost::is_class::value &&\ + !::boost::is_same::value &&\ + !::boost::move_detail::is_rv::value\ + , RETURN_VALUE >::type\ + PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u)\ + {\ + TYPE t(u);\ + return FWD_FUNCTION(arg1, ::boost::move(t));\ + }\ +// + +#elif (defined(_MSC_VER) && (_MSC_VER == 1600)) + +#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)\ + { return FWD_FUNCTION(arg1, static_cast(x)); }\ +\ + RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_RVALUE(TYPE) x) \ + { return FWD_FUNCTION(arg1, ::boost::move(x)); }\ +\ + template\ + typename ::boost::enable_if_c\ + < !::boost::is_same::value\ + , RETURN_VALUE >::type\ + PUB_FUNCTION(ARG1 arg1, const BOOST_MOVE_TEMPL_PARAM &u)\ + {\ + TYPE t(u);\ + return FWD_FUNCTION(arg1, ::boost::move(t));\ + }\ +// + +#else + +#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)\ + { return FWD_FUNCTION(arg1, static_cast(x)); }\ +\ + RETURN_VALUE PUB_FUNCTION(ARG1 arg1, BOOST_MOVE_CATCH_RVALUE(TYPE) x) \ + { return FWD_FUNCTION(arg1, ::boost::move(x)); }\ +// + +#endif + +#endif //#ifndef BOOST_MOVE_MOVE_HELPERS_HPP From d4983b7afeecfd83f244769582ea78bf038262c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 17 Mar 2011 16:41:04 +0000 Subject: [PATCH 3/8] Added to trunk [SVN r70067] --- doc/Jamfile.v2 | 38 + doc/html/boostbook.css | 538 ++++++++++++++ doc/html/images/blank.png | Bin 0 -> 392 bytes doc/html/images/caution.png | Bin 0 -> 1253 bytes doc/html/images/draft.png | Bin 0 -> 17539 bytes doc/html/images/home.png | Bin 0 -> 361 bytes doc/html/images/important.png | Bin 0 -> 726 bytes doc/html/images/next.png | Bin 0 -> 342 bytes doc/html/images/note.png | Bin 0 -> 495 bytes doc/html/images/prev.png | Bin 0 -> 338 bytes doc/html/images/tip.png | Bin 0 -> 456 bytes doc/html/images/toc-blank.png | Bin 0 -> 321 bytes doc/html/images/toc-minus.png | Bin 0 -> 262 bytes doc/html/images/toc-plus.png | Bin 0 -> 267 bytes doc/html/images/up.png | Bin 0 -> 370 bytes doc/html/images/warning.png | Bin 0 -> 1244 bytes doc/html/reference.css | 13 + doc/move.qbk | 789 +++++++++++++++++++++ example/Jamfile.v2 | 28 + example/copymovable.hpp | 46 ++ example/doc_clone_ptr.cpp | 152 ++++ example/doc_construct_forward.cpp | 105 +++ example/doc_file_descriptor.cpp | 87 +++ example/doc_how_works.cpp | 60 ++ example/doc_move_algorithms.cpp | 41 ++ example/doc_move_inserter.cpp | 48 ++ example/doc_move_iterator.cpp | 39 + example/movable.hpp | 49 ++ proj/vc7ide/Move.sln | 140 ++++ proj/vc7ide/back_move_inserter_test.vcproj | 134 ++++ proj/vc7ide/construct_forward_test.vcproj | 134 ++++ proj/vc7ide/conversion_test.vcproj | 134 ++++ proj/vc7ide/copy_elision_test.vcproj | 134 ++++ proj/vc7ide/copy_move_optimization.vcproj | 134 ++++ proj/vc7ide/doc_clone_ptr.vcproj | 139 ++++ proj/vc7ide/doc_construct_forward.vcproj | 139 ++++ proj/vc7ide/doc_file_descriptor.vcproj | 139 ++++ proj/vc7ide/doc_how_works.vcproj | 139 ++++ proj/vc7ide/doc_move_algorithms.vcproj | 139 ++++ proj/vc7ide/doc_move_inserter.vcproj | 139 ++++ proj/vc7ide/doc_move_iterator.vcproj | 139 ++++ proj/vc7ide/move_algorithm.vcproj | 134 ++++ proj/vc7ide/move_iterator_test.vcproj | 134 ++++ proj/vc7ide/move_test.vcproj | 139 ++++ test/Jamfile.v2 | 28 + test/back_move_inserter.cpp | 61 ++ test/construct_forward.cpp | 115 +++ test/conversion_test.cpp | 677 ++++++++++++++++++ test/copy_elision_test.cpp | 170 +++++ test/copy_move_optimization.cpp | 105 +++ test/move.cpp | 114 +++ test/move_algorithm.cpp | 55 ++ test/move_iterator.cpp | 104 +++ 53 files changed, 5652 insertions(+) create mode 100644 doc/Jamfile.v2 create mode 100644 doc/html/boostbook.css create mode 100644 doc/html/images/blank.png create mode 100644 doc/html/images/caution.png create mode 100644 doc/html/images/draft.png create mode 100644 doc/html/images/home.png create mode 100644 doc/html/images/important.png create mode 100644 doc/html/images/next.png create mode 100644 doc/html/images/note.png create mode 100644 doc/html/images/prev.png create mode 100644 doc/html/images/tip.png create mode 100644 doc/html/images/toc-blank.png create mode 100644 doc/html/images/toc-minus.png create mode 100644 doc/html/images/toc-plus.png create mode 100644 doc/html/images/up.png create mode 100644 doc/html/images/warning.png create mode 100644 doc/html/reference.css create mode 100644 doc/move.qbk create mode 100644 example/Jamfile.v2 create mode 100644 example/copymovable.hpp create mode 100644 example/doc_clone_ptr.cpp create mode 100644 example/doc_construct_forward.cpp create mode 100644 example/doc_file_descriptor.cpp create mode 100644 example/doc_how_works.cpp create mode 100644 example/doc_move_algorithms.cpp create mode 100644 example/doc_move_inserter.cpp create mode 100644 example/doc_move_iterator.cpp create mode 100644 example/movable.hpp create mode 100644 proj/vc7ide/Move.sln create mode 100644 proj/vc7ide/back_move_inserter_test.vcproj create mode 100644 proj/vc7ide/construct_forward_test.vcproj create mode 100644 proj/vc7ide/conversion_test.vcproj create mode 100644 proj/vc7ide/copy_elision_test.vcproj create mode 100644 proj/vc7ide/copy_move_optimization.vcproj create mode 100644 proj/vc7ide/doc_clone_ptr.vcproj create mode 100644 proj/vc7ide/doc_construct_forward.vcproj create mode 100644 proj/vc7ide/doc_file_descriptor.vcproj create mode 100644 proj/vc7ide/doc_how_works.vcproj create mode 100644 proj/vc7ide/doc_move_algorithms.vcproj create mode 100644 proj/vc7ide/doc_move_inserter.vcproj create mode 100644 proj/vc7ide/doc_move_iterator.vcproj create mode 100644 proj/vc7ide/move_algorithm.vcproj create mode 100644 proj/vc7ide/move_iterator_test.vcproj create mode 100644 proj/vc7ide/move_test.vcproj create mode 100644 test/Jamfile.v2 create mode 100644 test/back_move_inserter.cpp create mode 100644 test/construct_forward.cpp create mode 100644 test/conversion_test.cpp create mode 100644 test/copy_elision_test.cpp create mode 100644 test/copy_move_optimization.cpp create mode 100644 test/move.cpp create mode 100644 test/move_algorithm.cpp create mode 100644 test/move_iterator.cpp diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 new file mode 100644 index 0000000..f970d61 --- /dev/null +++ b/doc/Jamfile.v2 @@ -0,0 +1,38 @@ +# Boost.Move library documentation Jamfile +# +# Copyright Ion Gaztanaga 2009. +# 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. + + +import doxygen ; +import quickbook ; + +doxygen autodoc + : + [ glob ../../../boost/move/*.hpp ] + : + HIDE_UNDOC_MEMBERS=YES + HIDE_UNDOC_MEMBERS=YES + HIDE_UNDOC_CLASSES=YES + EXTRACT_PRIVATE=NO + ENABLE_PREPROCESSING=YES + MACRO_EXPANSION=YES + "PREDEFINED=\"BOOST_MOVE_DOXYGEN_INVOKED\"" + ; + +xml move : move.qbk ; + +boostbook standalone + : + move + : + boost.root=../../../.. + boost.libraries=../../../../libs/libraries.htm + generate.section.toc.level=3 + chunk.first.sections=1 + autodoc + ; diff --git a/doc/html/boostbook.css b/doc/html/boostbook.css new file mode 100644 index 0000000..e816cce --- /dev/null +++ b/doc/html/boostbook.css @@ -0,0 +1,538 @@ +/*============================================================================= + Copyright (c) 2004 Joel de Guzman + http://spirit.sourceforge.net/ + + Use, modification and distribution is subject to 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) +=============================================================================*/ + +/*============================================================================= + Body defaults +=============================================================================*/ + + body + { + margin: 1em; + font-family: sans-serif; + } + +/*============================================================================= + Paragraphs +=============================================================================*/ + + p + { + text-align: left; + font-size: 10pt; + line-height: 1.15; + } + +/*============================================================================= + Program listings +=============================================================================*/ + + /* Code on paragraphs */ + p tt.computeroutput + { + font-size: 10pt; + } + + pre.synopsis + { + font-size: 10pt; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + .programlisting, + .screen + { + font-size: 10pt; + display: block; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + +/*============================================================================= + Headings +=============================================================================*/ + + h1, h2, h3, h4, h5, h6 + { + text-align: left; + margin: 1em 0em 0.5em 0em; + font-weight: bold; + } + + h1 { font: 140% } + h2 { font: bold 140% } + h3 { font: bold 130% } + h4 { font: bold 120% } + h5 { font: italic 110% } + h6 { font: italic 100% } + + /* Top page titles */ + title, + h1.title, + h2.title + h3.title, + h4.title, + h5.title, + h6.title, + .refentrytitle + { + font-weight: bold; + margin-bottom: 1pc; + } + + h1.title { font-size: 140% } + h2.title { font-size: 140% } + h3.title { font-size: 130% } + h4.title { font-size: 120% } + h5.title { font-size: 110% } + h6.title { font-size: 100% } + + .section h1 + { + margin: 0em 0em 0.5em 0em; + font-size: 140%; + } + + .section h2 { font-size: 140% } + .section h3 { font-size: 130% } + .section h4 { font-size: 120% } + .section h5 { font-size: 110% } + .section h6 { font-size: 100% } + + /* Code on titles */ + h1 tt.computeroutput { font-size: 140% } + h2 tt.computeroutput { font-size: 140% } + h3 tt.computeroutput { font-size: 130% } + h4 tt.computeroutput { font-size: 120% } + h5 tt.computeroutput { font-size: 110% } + h6 tt.computeroutput { font-size: 100% } + +/*============================================================================= + Author +=============================================================================*/ + + h3.author + { + font-size: 100% + } + +/*============================================================================= + Lists +=============================================================================*/ + + li + { + font-size: 10pt; + line-height: 1.3; + } + + /* Unordered lists */ + ul + { + text-align: left; + } + + /* Ordered lists */ + ol + { + text-align: left; + } + +/*============================================================================= + Links +=============================================================================*/ + + a + { + text-decoration: none; /* no underline */ + } + + a:hover + { + text-decoration: underline; + } + +/*============================================================================= + Spirit style navigation +=============================================================================*/ + + .spirit-nav + { + text-align: right; + } + + .spirit-nav a + { + color: white; + padding-left: 0.5em; + } + + .spirit-nav img + { + border-width: 0px; + } + +/*============================================================================= + Table of contents +=============================================================================*/ + + .toc + { + margin: 1pc 4% 0pc 4%; + padding: 0.1pc 1pc 0.1pc 1pc; + font-size: 10pt; + line-height: 1.15; + } + + .toc-main + { + width: 600; + text-align: center; + margin: 1pc 1pc 1pc 10%; + padding: 2pc 1pc 3pc 1pc; + line-height: 0.1; + } + + .boost-toc + { + float: right; + padding: 0.5pc; + } + +/*============================================================================= + Tables +=============================================================================*/ + + .table-title, + div.table p.title + { + margin-left: 4%; + padding-right: 0.5em; + padding-left: 0.5em; + } + + .informaltable table, + .table table + { + width: 92%; + margin-left: 4%; + margin-right: 4%; + } + + div.informaltable table, + div.table table + { + padding: 4px; + } + + /* Table Cells */ + div.informaltable table tr td, + div.table table tr td + { + padding: 0.5em; + text-align: left; + } + + div.informaltable table tr th, + div.table table tr th + { + padding: 0.5em 0.5em 0.5em 0.5em; + border: 1pt solid white; + font-size: 120%; + } + +/*============================================================================= + Blurbs +=============================================================================*/ + + div.note, + div.tip, + div.important, + div.caution, + div.warning, + p.blurb + { + font-size: 10pt; + line-height: 1.2; + display: block; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + p.blurb img + { + padding: 1pt; + } + +/*============================================================================= + Variable Lists +=============================================================================*/ + + span.term + { + font-weight: bold; + font-size: 10pt; + } + + div.variablelist table tbody tr td + { + text-align: left; + vertical-align: top; + padding: 0em 2em 0em 0em; + font-size: 10pt; + } + + div.variablelist table tbody tr td p + { + margin: 0em 0em 0.5em 0em; + } + + /* Make the terms in definition lists bold */ + div.variablelist dl dt + { + font-weight: bold; + font-size: 10pt; + } + + div.variablelist dl dd + { + margin: 1em 0em 1em 2em; + font-size: 10pt; + } + +/*============================================================================= + Misc +=============================================================================*/ + + /* Title of books and articles in bibliographies */ + span.title + { + font-style: italic; + } + + span.underline + { + text-decoration: underline; + } + + span.strikethrough + { + text-decoration: line-through; + } + + /* Copyright, Legal Notice */ + div div.legalnotice p + { + font-size: 8pt; + text-align: left + } + +/*============================================================================= + Colors +=============================================================================*/ + + @media screen + { + /* Links */ + a + { + color: #0C7445; + } + + a:visited + { + color: #663974; + } + + h1 a, h2 a, h3 a, h4 a, h5 a, h6 a, + h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover, + h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited + { + text-decoration: none; /* no underline */ + color: #000000; + } + + /* Syntax Highlighting */ + .keyword { color: #0000AA; } + .identifier { color: #000000; } + .special { color: #707070; } + .preprocessor { color: #402080; } + .char { color: teal; } + .comment { color: #800000; } + .string { color: teal; } + .number { color: teal; } + .white_bkd { background-color: #E8FBE9; } + .dk_grey_bkd { background-color: #A0DAAC; } + + /* Copyright, Legal Notice */ + .copyright + { + color: #666666; + font-size: small; + } + + div div.legalnotice p + { + color: #666666; + } + + /* Program listing */ + pre.synopsis + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + .programlisting, + .screen + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + /* Blurbs */ + div.note, + div.tip, + div.important, + div.caution, + div.warning, + p.blurb + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + /* Table of contents */ + .toc + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + /* Table of contents */ + .toc-main + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + + /* Tables */ + div.informaltable table tr td, + div.table table tr td + { + border: 1px solid #DCDCDC; + background-color: #FAFFFB; + } + + div.informaltable table tr th, + div.table table tr th + { + background-color: #E3F9E4; + border: 1px solid #DCDCDC; + } + + /* Misc */ + span.highlight + { + color: #00A000; + } + } + + @media print + { + /* Links */ + a + { + color: black; + } + + a:visited + { + color: black; + } + + .spirit-nav + { + display: none; + } + + /* Program listing */ + pre.synopsis + { + border: 1px solid gray; + background-color: #FAFFFB; + } + + .programlisting, + .screen + { + border: 1px solid gray; + background-color: #FAFFFB; + } + + /* Table of contents */ + .toc + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + /* Table of contents */ + .toc-main + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + .informaltable table, + .table table + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + border-collapse: collapse; + background-color: #FAFFFB; + } + + /* Tables */ + div.informaltable table tr td, + div.table table tr td + { + border: 1px solid #DCDCDC; + background-color: #FAFFFB; + } + + div.informaltable table tr th, + div.table table tr th + { + border: 1px solid #DCDCDC; + background-color: #FAFFFB; + } + + /* Misc */ + span.highlight + { + font-weight: bold; + } + } diff --git a/doc/html/images/blank.png b/doc/html/images/blank.png new file mode 100644 index 0000000000000000000000000000000000000000..c387d424b21d641808bf44ca19f001bb7fde5d78 GIT binary patch literal 392 zcmeAS@N?(o;*#QGU|`_o^7L>CVqjos0AUU$1_lP7m~V3!7#LX69eo`c7&i8E|4C$J zU|`hsba4!+nDh3cqacF<&jEu2`=9%|$(e9fUAHz?KX;jNe>TH4hBb^4%p2Gec)1Qp hHJCDtioilcEFq2gFB6|f8Uq6ZgQu&X%Q~loCIIhfY*qjO literal 0 HcmV?d00001 diff --git a/doc/html/images/caution.png b/doc/html/images/caution.png new file mode 100644 index 0000000000000000000000000000000000000000..b056bccddb7f56b998b401bde72c561f64e65b4b GIT binary patch literal 1253 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 QFfcH9y85}Sb4q9e08q9V)&Kwi literal 0 HcmV?d00001 diff --git a/doc/html/images/home.png b/doc/html/images/home.png new file mode 100644 index 0000000000000000000000000000000000000000..04cc7bd01324e7cb6b16e2d4364908f61afdccc7 GIT binary patch literal 361 zcmeAS@N?(o<&xs%Vqjq4_4IHFVqjnp24NOv1_p+PI_>`q3=GW0PM#qg92~bF`afV` zU{DG032_w{5$x{laCWdedgO3IT#TBs!pxa7FJHd2ZR?gmf8VsUwEzGAFZ#1Vnt_3V zrzFTP_&)+L2;Dz-j)8%Jv%n*=n1O*?2!t6g-L3n>z`&qd;u=vBoS#-wo>-L1;G39S zl%JcLl9{OBmRXcqo?nz*tl%4=U}Rum(q6XaJOcxR7)XP2QEFmIW`3SRNM>#-gQ0=G zfw8`U$?^3)oD2*Md7dtgAr*6yZ}76HUUf)fW}a|EPJk~tFDYSdn~|u5#398qzC1h% zi2}kJ971eHj!g=Q3c@-ZBKHn32(s{Ui5vJd7)dfoNQoD4>LrNGF)(aQ+|KwpkNMqQ wrc2Tv3>$Y{n3;2o(?IP=gurHoV=N4vB6d^t3vVeiFfcH9y85}Sb4q9e02p6(&Hw-a literal 0 HcmV?d00001 diff --git a/doc/html/images/important.png b/doc/html/images/important.png new file mode 100644 index 0000000000000000000000000000000000000000..e257957c007b0348b700371d1897b51e6312435b GIT binary patch literal 726 zcmeAS@N?(o<&xs%Vqjq4_4IHFVqjp90AUVh1_p-fE6<){U|@I>;1l91z`!6NARr+j zp{c29X=&-?WEd5tnVc-)(<9N-W4U)P$J(`u zYu8%NnG@C1Q$1%+@|-!ebH&%LC11Oi{rC%?9YkQV1ow9W4oV|Nn_U@gtbm`KyYnQHFyLRi=t$X+G zJ$CHaxpU{PUAuPg-o59~pTB?q{`>du|NsAAd+G2!1_lPkByV>Y=kyD_Nem2(;+`&! zAr-fBCvgWKGT=FG?E2Ag>cRt8PI})72oaewwbM;~?$+P`?jK**ANc;;{@1aS;^i}i zPIzy0TFS1r%dJU6?5Wv<`yY!W#D0B9-o@C%qCfHCmev?%zk7!>7H^oXrSQn8;PFn| zR;!gPU%cLaXDFL0%4W~BVd}pB91F~@yszQqauBZl&Xn*!?zUaC%=)dxyj%hMua-GA zER| zDNig)WpL0?*7VFxOi%SqOwUZtRxr^s(z8&owA44S&^IttNG{4OE~#|Ltt>9dOx8;+ z)=McZ$j>X$OU}=oxJz*d0|SE=*tpE}yu^~yqEv=tCVqjnp24NOv1_p+PI_>`q3=GW0PM#qg92~bF`afV` zU{DG032_w{5$x{lFg7;cwslLOzpt9I!iwcfA3b__`SPWNxEN;#yZ`_H>j~K>GB7ak zlmz(&|3?4@q5J2~F)%Q27I;J!Gca%qfiUBxyLEpU7#LJbTq8;n};e2?i~kV)qVAc*MlQ~iPEwq7*nr2ic3*3&H#ax4GdJ&l(GnKNKxaqiKu6hw+Ub)`a+jX$dHg)z z`@Y^|p819UrY0+}Ec)|>*Jbq;TctgWznJ(o74x&oD|8%JZF(ZllCtOc9FGNG4ChPD zez56(C7@zJhD-x|Vg%h-{YDN|SB1O_Vf$_<@oU1aJO11r zr(c-djm_tt_x5VlnRCm}Kbx8UT`q3=GW0PM#qg92~bF`afV` zU{DG032_w{5ll-UX-Pz&nV3!aV^Z)<QK$!8;-MT*v3=FCzt`Q}{`DrEPiAAXlzKO|2 z`MIennTZN+nMJAP`9;~q3ce8vMg|5Z?PY7uGcYiSfiyT5r6!hS=I1GdWag$a7#ips z80#CD9ADqV$-ux6=IP=XQZXm_1}{sTLJ~9cgd2wpq>q&(JZLf6ZeXy%aV8%R&r1O{ zj}20XT6npbW;!^sT@6q$NMPXQa&lm1W^U?K=~^Ook|m{hVvche^Q6-g?(V)Vn8U=t YoEqFEkjD9gfq{X+)78&qol`;+0Plow*Z=?k literal 0 HcmV?d00001 diff --git a/doc/html/images/tip.png b/doc/html/images/tip.png new file mode 100644 index 0000000000000000000000000000000000000000..07ef20f8566cffc1379593d257b70cd388b77eb3 GIT binary patch literal 456 zcmeAS@N?(o<&xs%Vqjq4_4IHFVqjp9WME*B;9y{2V9>h9DaF9Rz?9_e?!v&Zs#n>F zfq~(+r;B4q#jVmwy9Ey`@Hj{+YFG5EnPj%qd-|FOLE0HCUfZWgHBJ)@5lZyt<>KVD zyWcqPUr>QgF%ln1NMyHmmVvr>?nXee;PB&*%IS zrnzQL-@JsL6gu;Ay@^OEA`#GK)(p9dav+OEQ!7Qj7Ic zN(=JyO7xQRb0_Xn+yM$tuyL8`d5I;ZMX3y_sg@}g=H|whX342WX6A{hNd|`ImMO-j yX%>b_Mv2Kn#=q1V7#R3Kx&ji@QyGj*D~wFE4YUpRedJsZiXcx{KbLh*2~7ZGd!Z`; literal 0 HcmV?d00001 diff --git a/doc/html/images/toc-blank.png b/doc/html/images/toc-blank.png new file mode 100644 index 0000000000000000000000000000000000000000..75b24d6fc4aafdebbc3b9adfe816fbbc546ea3e9 GIT binary patch literal 321 zcmeAS@N?(o;*#QGU|`_o^7L>CVqjq4XJBC9WMO7tV31#!ox;GtU=ZLF;>y6l&;Z5_ zV5)(kfuW({z<~n|4GsSp7#RLD{0CG2!L0xP|N9H8c``6CFeZ7syD)UH%6c#`Fvxkj zIEGZ*O8)VG|9^XdnuH(xj0$XGf&v)|3)s#uFig4NbSXn_;{yf;2Imsjh?3y^w370~ zqErS44P{Nw+{E-$-^BFHCVqjq4XJBC9W2%2N;(A7e1fPz^EY4<9WS5%buZDw_sh==UuK03=GaCt`Q}{ z`DrEPiAAXl4jRgup1FzXslJKnnaSA-CVEDC77CV@`UV#I28IgBMVZAVl@7U;#U+`^ zda1>FDWwJZc_n(u`MDE!DehokV9){^mzkcISW;S)%8;6zW@2cZnr32dYGh(!V3KBO zkZfX-Vv%f~VrZ0TlzO-0-z>1VK-vNl(^DA?O)D(54YUo+%RYe2WAJqKb6Mw<&;$Tl C3r%AH literal 0 HcmV?d00001 diff --git a/doc/html/images/toc-plus.png b/doc/html/images/toc-plus.png new file mode 100644 index 0000000000000000000000000000000000000000..29fada25c1d6c039ab4ad5682d3a11bb80b56781 GIT binary patch literal 267 zcmeAS@N?(o;*#QGU|`_o^7L>CVqjq4XJBC9W2%2N;(ASN<&d;gh5T!wGh0r7MeP_Gj5M1bO9bN||Y8!oa}b zT;dv05}cn_Ql40p%HW`(tm&DXn4apJn4X!Otze>Oq-UXEX{m2up>JTQkX)2mTvF+f zTUlI^nXH#utd~++ke^qgmzR+Sn6#IzInThrAO_OlT$Gwvl9`{U5R#dj z%3x@qZ(yu%U~+tY4<`cyLy@P8V@SoEspmFwHW&!FJyeg_(XezvV9WvAI|r@_>dZZG zPW6aiOT!J--9O?NG0%AP;}ge|4lDQN4=-}8`?JGwx}?mMnO)OdyQdu$nQCjPRV}jm z$u!Qa8E-cQ-r3Nz>Y(YPTd#BPEH+&8GWqfD!}4*53%dA!%#3$cIv;a~fq{X+)78&q Iol`;+0POUaApigX literal 0 HcmV?d00001 diff --git a/doc/html/images/warning.png b/doc/html/images/warning.png new file mode 100644 index 0000000000000000000000000000000000000000..74fc1ba2b4a7693f381d09607b6c2aaca3c043f7 GIT binary patch literal 1244 zcmeAS@N?(o<&xs%Vqjq4_4IHFVqjp90AUVh1_p-fE6<){U|?nl@Ck9{U|ZJ?} zOD!#zdU-8vX<0gD%F?Av*D^4yH8fm1Wy)3thOL^KTYGx8&Y81y>C&xRx9(+N*t>S^ z-mP1YF)$nx5I80waqQT!a|{gU1O(1WNSxEuyvD$AO;hvQwQKhn81CJ>_nd*@xuW9p z=g;3WFudpBc>n(WcLs*<-@pH7VE8`@Mnix~Ay8obcnSjp17ni6y9+}HtE>kD1H%hX z7srr_Te*{J^P3C=j=i7ad*|7am&=$<`NUgQ_e@pI<-PyEc$_`T z-}ks+llM|~rIOr~k12h5MQt-@+ihAJ>T>9>ci#Q%XzNS6?G0G-6!*_zE@WU}a4vC; zC<)F_D=AMbN@Z}+P}cO!O-xVqO-#>B&Q>tdGt#qAu(Z@Su+TR!R7ft$EH0^Z$gM0c z$xPNuE!ImZEy&L+(M!(How!SJ2Ll6x7TCDV^t{B9(xOy`WD}z#^Aw{LQ!|sq#3WM- z3kyp_OLI$e1LHIUqa+hkf5H2c85kJ&K)M1F(^DCYOe%~_v< swap(T& a, T& b) + { + T tmp(a); // now we have two copies of a + a = b; // now we have two copies of b + b = tmp; // now we have two copies of tmp (aka a) + } + +But, we didn't want to have any copies of a or b, we just wanted to swap them. Let's try again: + +[c++] + + template swap(T& a, T& b) + { + T tmp(::boost::move(a)); + a = ::boost::move(b); + b = ::boost::move(tmp); + } + +This `move()` gives its target the value of its argument, but is not obliged to preserve the value +of its source. So, for a `vector`, `move()` could reasonably be expected to leave its argument as +a zero-capacity vector to avoid having to copy all the elements. In other words, [*move is a potentially +destructive copy]. + +In this particular case, we could have optimized swap by a specialization. However, we can't +specialize every function that copies a large object just before it deletes or overwrites it. That +would be unmanageable. + +In C++0x, move semantics are implemented with the introduction of rvalue references. They allow us to +implement `move()` without verbosity or runtime overhead. [*Boost.Move] is a library that offers tools +to implement those move semantics not only in compilers with `rvalue references` but also in compilers +conforming to C++03. + +[endsect] + +[section:implementing_movable_classes Implementing copyable and movable classes] + +[import ../example/doc_clone_ptr.cpp] + +[section:copyable_and_movable_cpp0x Copyable and movable classes in C++0x] + +Consider a simple handle class that owns a resource and also provides copy semantics +(copy constructor and assignment). For example a `clone_ptr` might own a pointer, and call +`clone()` on it for copying purposes: + +[c++] + + template + class clone_ptr + { + private: + T* ptr; + + public: + // construction + explicit clone_ptr(T* p = 0) : ptr(p) {} + + // destruction + ~clone_ptr() { delete ptr; } + + // copy semantics + clone_ptr(const clone_ptr& p) + : ptr(p.ptr ? p.ptr->clone() : 0) {} + + clone_ptr& operator=(const clone_ptr& p) + { + if (this != &p) + { + T *p = p.ptr ? p.ptr->clone() : 0; + delete ptr; + ptr = p; + } + return *this; + } + + // move semantics + clone_ptr(clone_ptr&& p) + : ptr(p.ptr) { p.ptr = 0; } + + clone_ptr& operator=(clone_ptr&& p) + { + std::swap(ptr, p.ptr); + delete p.ptr; + p.ptr = 0; + return *this; + } + + // Other operations... + }; + +`clone_ptr` has expected copy constructor and assignment semantics, duplicating resources when copying. +Note that copy constructing or assigning a `clone_ptr` is a relatively expensive operation: + +[copy_clone_ptr] + +`clone_ptr` is code that you might find in today's books on C++, except for the part marked as +`move semantics`. That part is implemented in terms of C++0x `rvalue references`. You can find +some good introduction and tutorials on rvalue references in these papers: + +* [@http://www.artima.com/cppsource/rvalue.html ['A Brief Introduction to Rvalue References]] +* [@http://blogs.msdn.com/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx ['Rvalue References: C++0x Features in VC10, Part 2]] + +When the source of the copy is known to be an `rvalue` (e.g.: a temporary object), one can avoid the +potentially expensive `clone()` operation by pilfering source's pointer (no one will notice!). The move +constructor above does exactly that, leaving the rvalue in a default constructed state. The move assignment +operator simply does the same freeing old resources. + +Now when code tries to copy an rvalue `clone_ptr`, or if that code explicitly gives permission to +consider the source of the copy an rvalue (using `boost::move`), the operation will execute much faster. + +[move_clone_ptr] + +[endsect] + +[section:copyable_and_movable_cpp03 Copyable and movable classes in portable syntax for both C++03 and C++0x compilers] + +Many aspects of move semantics can be emulated for compilers not supporting `rvalue references` +and [*Boost.Move] offers tools for that purpose. With [*Boost.Move] we can write `clone_ptr` +so that it will work both in compilers with rvalue references and those who conform to C++03. +You just need to follow these simple steps: + +* Put the following macro in the [*private] section: + [macroref BOOST_COPYABLE_AND_MOVABLE BOOST_COPYABLE_AND_MOVABLE(classname)] +* Left copy constructor as is. +* Write a copy assignment taking the parameter as + [macroref BOOST_COPY_ASSIGN_REF BOOST_COPY_ASSIGN_REF(classname)] +* Write a move constructor and a move assignment taking the parameter as + [macroref BOOST_RV_REF BOOST_RV_REF(classname)] + +Let's see how are applied to `clone_ptr`: + +[clone_ptr_def] + +[endsect] + +[*Question]: What about types that don't own resources? (E.g. `std::complex`?) + +No work needs to be done in that case. The copy constructor is already optimal. + +[endsect] + +[section:composition_inheritance Composition or inheritance] + +For classes made up of other classes (via either composition or inheritance), the move constructor +and move assignment can be easily coded using the `boost::move` function: + +[clone_ptr_base_derived] + +[important Due to limitations in the emulation code, a cast to `Base &` is needed before moving the base part in the move +constructor and call Base's move constructor instead of the copy constructor.] + +Each subobject will now be treated individually, calling move to bind to the subobject's move +constructors and move assignment operators. `Member` has move operations coded (just like +our earlier `clone_ptr` example) which will completely avoid the tremendously more expensive +copy operations: + +[clone_ptr_move_derived] + +Note above that the argument x is treated as a lvalue reference. That's why it is necessary to +say `move(x)` instead of just x when passing down to the base class. This is a key safety feature of move +semantics designed to prevent accidently moving twice from some named variable. All moves from +lvalues occur explicitly. + +[endsect] + +[section:movable_only_classes Movable but Non-Copyable Types] + +Some types are not amenable to copy semantics but can still be made movable. For example: + +* `unique_ptr` (non-shared, non-copyable ownership) +* A type representing a thread of execution +* A type representing a file descriptor + +By making such types movable (though still non-copyable) their utility is tremendously +increased. Movable but non-copyable types can be returned by value from factory functions: + +[c++] + + file_descriptor create_file(/* ... */); + //... + file_descriptor data_file; + //... + data_file = create_file(/* ... */); // No copies! + +In the above example, the underlying file handle is passed from object to object, as long +as the source `file_descriptor` is an rvalue. At all times, there is still only one underlying file +handle, and only one `file_descriptor` owns it at a time. + +To write a movable but not copyable type in portable syntax, you need to follow these simple steps: + +* Put the following macro in the [*private] section: + [macroref BOOST_MOVABLE_BUT_NOT_COPYABLE BOOST_MOVABLE_BUT_NOT_COPYABLE(classname)] +* Write a move constructor and a move assignment taking the parameter as + [macroref BOOST_RV_REF BOOST_RV_REF(classname)] + +Here's the definition of `file descriptor` using portable syntax: + +[import ../example/doc_file_descriptor.cpp] +[file_descriptor_def] + +[/ + /Many standard algorithms benefit from moving elements of the sequence as opposed to + /copying them. This not only provides better performance (like the improved `swap` + /implementation described above), but also allows these algorithms to operate on movable + /but non-copyable types. For example the following code sorts a `vector>` + /based on comparing the pointed-to types: + / + /[c++] + / + / struct indirect_less + / { + / template + / bool operator()(const T& x, const T& y) + / {return *x < *y;} + / }; + / ... + / std::vector> v; + / ... + / std::sort(v.begin(), v.end(), indirect_less()); + / + / + /As sort moves the unique_ptr's around, it will use swap (which no longer requires Copyability) + /or move construction / move assignment. Thus during the entire algorithm, the invariant that + /each item is owned and referenced by one and only one smart pointer is maintained. If the + /algorithm were to attempt a copy (say by programming mistake) a compile time error would result. + /] + +[endsect] + +[section:move_and_containers Containers and move semantics] + +Movable but non-copyable types can be safely inserted into containers and +movable and copyable types are more efficiently handled if those containers +internally use move semantics instead of copy semantics. +If the container needs to "change the location" of an element +internally (e.g. vector reallocation) it will move the element instead of copying it. +[*Boost.Interprocess] containers are move-aware so you can write the following: + +[file_descriptor_example] + +[endsect] + +[section:construct_forwarding Constructor Forwarding] + +Consider writing a generic factory function that returns an object for a newly +constructed generic type. Factory functions such as this are valuable for encapsulating +and localizing the allocation of resources. Obviously, the factory function must accept +exactly the same sets of arguments as the constructors of the type of objects constructed: + +[c++] + + template T* factory_new() + { return new T(); } + + template T* factory_new(a1) + { return new T(a1); } + + template T* factory_new(a1, a2) + { return new T(a1, a2); } + +Unfortunately, in C++03 the much bigger issue with this approach is that the N-argument case +would require 2^N overloads, immediately discounting this as a general solution. Fortunately, +most constructors take arguments by value, by const-reference or by rvalue reference. If these +limitations are accepted, the forwarding emulation of a N-argument case requires just N overloads. +This library makes this emulation easy with the help of `BOOST_FWD_REF` and +`boost::forward`: + +[import ../example/doc_construct_forward.cpp] +[construct_forward_example] + +Constructor forwarding comes handful to implement placement insertion in containers with +just N overloads if the implementor accepts the limitations of this type of forwarding for +C++03 compilers. In compilers with rvalue references perfect forwarding is achieved. + +[endsect] + +[/[section:perfect_forwarding Perfect Forwarding] + / + /Consider writing a generic factory function that returns a std::shared_ptr for a newly + /constructed generic type. Factory functions such as this are valuable for encapsulating + /and localizing the allocation of resources. Obviously, the factory function must accept + /exactly the same sets of arguments as the constructors of the type of objects constructed. + /Today this might be coded as: + / + /[c++] + / + / template + / std::shared_ptr + / factory() // no argument version + / { + / return std::shared_ptr(new T); + / } + / + / template + / std::shared_ptr + / factory(const A1& a1) // one argument version + / { + / return std::shared_ptr(new T(a1)); + / } + / + / // all the other versions + / + / + /In the interest of brevity, we will focus on just the one-parameter version. For example: + / + / [c++] + / + / std::shared_ptr p = factory(5); + / + / + / [*Question]: What if T's constructor takes a parameter by non-const reference? + / + / In that case, we get a compile-time error as the const-qualifed argument of the factory + / function will not bind to the non-const parameter of T's constructor. + / + / To solve that problem, we could use non-const parameters in our factory functions: + / + / [c++] + / + / template + / std::shared_ptr + / factory(A1& a1) + / { + / return std::shared_ptr(new T(a1)); + / } + / + / + / This is much better. If a const-qualified type is passed to the factory, the const will + / be deduced into the template parameter (A1 for example) and then properly forwarded to + / T's constructor. Similarly, if a non-const argument is given to factory, it will be + / correctly forwarded to T's constructor as a non-const. Indeed, this is precisely how + /forwarding applications are coded today (e.g. `std::bind`). + / + /However, consider: + / + /[c++] + / + / std::shared_ptr p = factory(5); // error + / A* q = new A(5); // ok + / + / + /This example worked with our first version of factory, but now it's broken: The "5" + /causesthe factory template argument to be deduced as int& and subsequently will not + /bind to the rvalue "5". Neither solution so far is right. Each breaks reasonable and + /common code. + / + /[*Question]: What about overloading on every combination of AI& and const AI&? + / + /This would allow use to handle all examples, but at a cost of an exponential explosion: + /For our two-parameter case, this would require 4 overloads. For a three-parameter factory + /we would need 8 additional overloads. For a four-parameter factory we would need 16, and + /so on. This is not a scalable solution. + / + /Rvalue references offer a simple, scalable solution to this problem: + / + /[c++] + / + / template + / std::shared_ptr + / factory(A1&& a1) + / { + / return std::shared_ptr(new T(std::forward(a1))); + / } + / + / Now rvalue arguments can bind to the factory parameters. If the argument is const, that + / fact gets deduced into the factory template parameter type. + / + / [*Question]: What is that forward function in our solution? + / + / Like move, forward is a simple standard library function used to express our intent + / directly and explicitly, rather than through potentially cryptic uses of references. + / We want to forward the argument a1, so we simply say so. + / + / Here, forward preserves the lvalue/rvalue-ness of the argument that was passed to factory. + / If an rvalue is passed to factory, then an rvalue will be passed to T's constructor with + / the help of the forward function. Similarly, if an lvalue is passed to factory, it is + / forwarded to T's constructor as an lvalue. + / + / The definition of forward looks like this: + / + / [c++] + / + / template + / struct identity + / { + / typedef T type; + / }; + / + / template + / T&& forward(typename identity::type&& a) + / { + / return a; + / } + / + /[endsect] + / + /] + +[section:move_iterator Move iterators] + +[c++] + + template + class move_iterator; + + template + move_iterator make_move_iterator(const It &it); + +[classref boost::move_iterator 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: `boost::move(*underlying_iterator)` +It is a read-once iterator, but can have up to random access traversal characteristics. + +`move_iterator` is very useful because some generic algorithms and container insertion functions +can be called with move iterators to replace copying with moving. For example: + +[import ../example/movable.hpp] +[movable_definition] + +`movable` objects can be moved from one container to another using move iterators and insertion +and assignment operations.w + +[import ../example/doc_move_iterator.cpp] +[move_iterator_example] + +[endsect] + +[section:move_inserters Move inserters] + +Similar to standard insert iterators, it's possible to deal with move insertion in the same way +as writing into an array. A special kind of iterator adaptors, called move insert iterators, are +provided with this library. With regular iterator classes, + +[c++] + + while (first != last) *result++ = *first++; + +causes a range [first,last) to be copied into a range starting with result. The same code with +result being an move insert iterator will move insert corresponding elements into the container. +This device allows all of the copying algorithms in the library to work in the move insert mode +instead of the regular overwrite mode. This library offers 3 move insert iterators and their +helper functions: + +[c++] + + // Note: C models Container + template + class back_move_insert_iterator; + + template + back_move_insert_iterator back_move_inserter(C& x); + + template + class front_move_insert_iterator; + + template + front_move_insert_iterator front_move_inserter(C& x); + + template + class move_insert_iterator; + + template + move_insert_iterator move_inserter(C& x, typename C::iterator it); + + +A move insert iterator is constructed from a container and possibly one of its iterators pointing +to where insertion takes place if it is neither at the beginning nor at the end of the container. +Insert iterators satisfy the requirements of output iterators. `operator*` returns the move insert +iterator itself. The assignment `operator=(T& x)` is defined on insert iterators to allow writing +into them, it inserts x right before where the insert iterator is pointing. In other words, an +`insert iterator` is like a cursor pointing into the container where the insertion takes place. +`back_move_iterator` move inserts elements at the end of a container, `front_insert_iterator` +move inserts elements at the beginning of a container, and `move_insert_iterator` move inserts +elements where the iterator points to in a container. `back_move_inserter`, `front_move_inserter`, +and `move_inserter` are three functions making the insert iterators out of a container. Here's +an example of how to use them: + +[import ../example/doc_move_inserter.cpp] +[move_inserter_example] + +[endsect] + +[section:move_algorithms Move algorithms] + +The standard library offers several copy-based algorithms. Some of them, like `std::copy` or +`std::uninitialized_copy` are basic building blocks for containers and other data structures. +This library offers move-based functions for those purposes: + +[c++] + + template O move(I, I, O); + template O move_backward(I, I, O); + template F uninitialized_move(I, I, F); + template F uninitialized_copy_or_move(I, I, F); + + +The first 3 are move variations of their equivalent copy algorithms, but copy assignment and +copy construction are replaced with move assignment and construction. The last one has the +same behaviour as `std::uninitialized_copy` but since several standand library implementations +don't play very well with `move_iterator`s, this version is a portable version for those +willing to use move iterators. + +[import ../example/doc_move_algorithms.cpp] +[move_algorithms_example] + +[endsect] + +[section:emulation_limitations Emulation limitations] + +Like any emulation effort, the library has some limitations users should take in +care to achieve portable and efficient code when using the library with C++03 conformant compilers: + +[section:emulation_limitations_base Initializing base classes] + +When initializing base classes in move constructors, users must +cast the reference to a base class reference before moving it. Example: + +[c++] + + //Portable and efficient + Derived(BOOST_RV_REF(Derived) x) // Move ctor + : Base(boost::move(static_cast(x))), + mem_(boost::move(x.mem_)) { } + + +If casting is not performed the emulation will not move construct +the base class, because no conversion is available from `BOOST_RV_REF(Derived)` +to `BOOST_RV_REF(Base)`. Without the cast we might obtain a compilation +error (for non-copyable types) or a less-efficient move constructor (for copyable types): + +[c++] + + //If Derived is copyable, then Base is copy-constructed. + //If not, a compilation error is issued + Derived(BOOST_RV_REF(Derived) x) // Move ctor + : Base(boost::move(x)), + mem_(boost::move(x.mem_)) { } + +[endsect] + +[section:template_parameters Template parameters for perfect forwarding] + +The emulation can't deal with C++0x reference collapsing rules that allow perfect forwarding: + +[c++] + + //C++0x + template + void forward_function(T &&t) + { inner_function(std::forward(t); } + + //Wrong C++03 emulation + template + void forward_function(BOOST_RV_REF t) + { inner_function(boost::forward(t); } + +In C++03 emulation BOOST_RV_REF doesn't catch any const rlvalues. For more details on +forwarding see [link move.construct_forwarding Constructor Forwarding] chapter. + +[endsect] + +[section:emulation_limitations_binding Binding of rvalue references to lvalues] + +The +[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1690.html first rvalue reference] +proposal allowed the binding of rvalue references to lvalues: + +[c++] + + func(Type &&t); + //.... + + Type t; //Allowed + func(t) + + +Later, as explained in +[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2812.html ['Fixing a Safety Problem with Rvalue References]] +this behaviour was considered dangerous and eliminated this binding so that rvalue references adhere to the +principle of type-safe overloading: ['Every function must be type-safe in isolation, without regard to how it has been overloaded] + +[*Boost.Move] can't emulate this type-safe overloading principle for C++03 compilers: + +[c++] + + //Allowed by move emulation + movable m; + BOOST_RV_REF(movable) r = m; + +[endsect] + +[section:assignment_operator Assignment operator in classes derived from or holding copyable and movable types] + +The macro [macroref BOOST_COPYABLE_AND_MOVABLE BOOST_COPYABLE_AND_MOVABLE] needs to +define a copy constructor for `copyable_and_movable` taking a non-const parameter in C++03 compilers: + +[c++] + + //Generated by BOOST_COPYABLE_AND_MOVABLE + copyable_and_movable &operator=(copyable_and_movable&){/**/} + +Since the non-const overload of the copy constructor is generated, compiler-generated +assignment operators for classes containing `copyable_and_movable` +will get the non-const copy constructor overload, which will surely surprise users: + +[c++] + + class holder + { + copyable_and_movable c; + }; + + void func(const holder& h) + { + holder copy_h(h); //<--- ERROR: can't convert 'const holder&' to 'holder&' + //Compiler-generated copy constructor is non-const: + // holder& operator(holder &) + //!!! + } + +This limitation forces the user to define a const version of the copy assignment, +in all classes holding copyable and movable classes which might annoying in some cases. + +An alternative is to implement a single `operator =()` for copyable and movable classes +[@http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ using "pass by value" semantics]: + +[c++] + + T& operator=(T x) // x is a copy of the source; hard work already done + { + swap(*this, x); // trade our resources for x's + return *this; // our (old) resources get destroyed with x + } + +However, "pass by value" is not optimal for classes (like containers, strings, etc.) that reuse resources +(like previously allocated memory) when x is assigned from a lvalue. + +[endsect] + +[endsect] + +[section:how_the_library_works How the library works] + +[*Boost.Move] is based on macros that are expanded to true rvalue references in C++0x compilers +and emulated rvalue reference classes and conversion operators in C++03 compilers. + +In C++03 compilers [*Boost.Move] defines a class named `::boost::rv`: + +[c++] + + template + class rv : public T + { + rv(); + ~rv(); + rv(rv const&); + void operator=(rv const&); + }; + +which is convertible to the movable base class (usual C++ derived to base conversion). When users mark +their classes as [macroref BOOST_MOVABLE_BUT_NOT_COPYABLE BOOST_MOVABLE_BUT_NOT_COPYABLE] or +[macroref BOOST_COPYABLE_AND_MOVABLE BOOST_COPYABLE_AND_MOVABLE], these macros define conversion +operators to references to `::boost::rv`: + +[c++] + + #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\ + public:\ + operator ::BOOST_MOVE_NAMESPACE::rv&() \ + { return *reinterpret_cast< ::BOOST_MOVE_NAMESPACE::rv* >(this); }\ + operator const ::BOOST_MOVE_NAMESPACE::rv&() const \ + { return *reinterpret_cast* >(this); }\ + private:\ + //More stuff... + +[macroref BOOST_MOVABLE_BUT_NOT_COPYABLE BOOST_MOVABLE_BUT_NOT_COPYABLE] also declares a +private copy constructor and assignment. [macroref BOOST_COPYABLE_AND_MOVABLE BOOST_COPYABLE_AND_MOVABLE] +defines a non-const copy constructor `TYPE &operator=(TYPE&)` that forwards to a const version: + + #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\ + public:\ + TYPE& operator=(TYPE &t)\ + { this->operator=(static_cast &>(const_cast(t))); return *this;}\ + //More stuff... + +In C++0x compilers `BOOST_COPYABLE_AND_MOVABLE` expands to nothing and `BOOST_MOVABLE_BUT_NOT_COPYABLE` +declares copy constructor and assigment operator private. + +When users define the [macroref BOOST_RV_REF BOOST_RV_REF] overload of a copy constructor/assignment, in +C++0x compilers it is expanded to a rvalue reference (`T&&`) overload and in C++03 compilers it is expanded +to a `::boost::rv &` overload: + +[c++] + + #define BOOST_RV_REF(TYPE) ::boost::rv< TYPE >& \ + +When users define the [macroref BOOST_COPY_ASSIGN_REF BOOST_COPY_ASSIGN_REF] overload, +it is expanded to a usual copy assignment (`const T &`) overload in C++0x compilers and +to a `const ::boost::rv &` overload in C++03 compilers: + +[c++] + + #define BOOST_COPY_ASSIGN_REF(TYPE) const ::boost::rv< TYPE >& + +As seen, in [*Boost.Move] generates efficient and clean code for C++0x move +semantics, without modifying any resolution overload. For C++03 compilers +when overload resolution is performed these are the bindings: + +* a) non-const rvalues (e.g.: temporaries), bind to `::boost::rv< TYPE >&` +* b) const rvalue and lvalues, bind to `const ::boost::rv< TYPE >&` +* c) non-const lvalues (e.g. non-const references) bind to `TYPE&` + +The library does not define the equivalent of +[macroref BOOST_COPY_ASSIGN_REF BOOST_COPY_ASSIGN_REF] for copy construction (say, `BOOST_COPY_CTOR_REF`) +because nearly all modern compilers implement RVO and this is much more efficient than any move emulation. +[funcref boost::move move] just casts `TYPE &` into `::boost::rv &`. + +Here's an example that demostrates how different rlvalue objects bind to `::boost::rv` references in the +presence of three overloads and the conversion operators in C++03 compilers: + +[import ../example/doc_how_works.cpp] +[how_works_example] + +[endsect] + + +[section:thanks_to Thanks and credits] + +Thanks to all that developed ideas for move emulation: the first emulation was based on Howard Hinnant +emulation code for `unique_ptr`, David Abrahams suggested the use of `class rv` class, +and Klaus Triendl discovered how to bind const rlvalues using `class rv`. + +Many thanks to all boosters that have tested, reviewed and improved the library. + +[endsect] + +[xinclude autodoc.xml] diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 new file mode 100644 index 0000000..d7de3e6 --- /dev/null +++ b/example/Jamfile.v2 @@ -0,0 +1,28 @@ +############################################################################## +## +## (C) Copyright Ion Gaztanaga 2008-2009 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) +## +## +############################################################################## +rule test_all +{ + local all_rules = ; + + for local fileb in [ glob *.cpp ] + { + all_rules += [ run $(fileb) + : # additional args + : # test-files + : # requirements + ] ; + } + + return $(all_rules) ; +} + +test-suite move_example : [ test_all r ] +: static +; + diff --git a/example/copymovable.hpp b/example/copymovable.hpp new file mode 100644 index 0000000..c3b4793 --- /dev/null +++ b/example/copymovable.hpp @@ -0,0 +1,46 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009. +// 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_TEST_COPYMOVABLE_HPP +#define BOOST_MOVE_TEST_COPYMOVABLE_HPP + +//[movable_definition +//header file "copy_movable.hpp" +#include + +//A copy_movable class +class copy_movable +{ + BOOST_COPYABLE_AND_MOVABLE(copy_movable) + int value_; + + public: + copy_movable() : value_(1){} + + //Move constructor and assignment + copy_movable(BOOST_RV_REF(copy_movable) m) + { value_ = m.value_; m.value_ = 0; } + + copy_movable(const copy_movable &m) + { value_ = m.value_; } + + copy_movable & operator=(BOOST_RV_REF(copy_movable) m) + { value_ = m.value_; m.value_ = 0; return *this; } + + copy_movable & operator=(BOOST_COPY_ASSIGN_REF(copy_movable) m) + { value_ = m.value_; return *this; } + + bool moved() const //Observer + { return value_ == 0; } +}; + +//] + +#endif //BOOST_MOVE_TEST_COPYMOVABLE_HPP diff --git a/example/doc_clone_ptr.cpp b/example/doc_clone_ptr.cpp new file mode 100644 index 0000000..e86e64b --- /dev/null +++ b/example/doc_clone_ptr.cpp @@ -0,0 +1,152 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009. +// 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 + +//[clone_ptr_base_derived +class Base +{ + BOOST_COPYABLE_AND_MOVABLE(Base) + + public: + Base(){} + + // Compiler-generated copy constructor... + + Base(BOOST_RV_REF(Base) x) {/**/} // Move ctor + + Base& operator=(BOOST_RV_REF(Base) x) + {/**/ return *this;} // Move assign + + Base& operator=(BOOST_COPY_ASSIGN_REF(Base) x) + {/**/ return *this;} // Copy assign + + virtual Base *clone() const + { return new Base(*this); } +}; + +class Member +{ + BOOST_COPYABLE_AND_MOVABLE(Member) + + public: + Member(){} + + // Compiler-generated copy constructor... + + Member(BOOST_RV_REF(Member)) {/**/} // Move ctor + + Member &operator=(BOOST_RV_REF(Member)) // Move assign + {/**/ return *this; } + + Member &operator=(BOOST_COPY_ASSIGN_REF(Member)) // Copy assign + {/**/ return *this; } +}; + +class Derived : public Base +{ + BOOST_COPYABLE_AND_MOVABLE(Derived) + Member mem_; + + public: + Derived(){} + + // Compiler-generated copy constructor... + + Derived(BOOST_RV_REF(Derived) x) // Move ctor + : Base(boost::move(static_cast(x))), + mem_(boost::move(x.mem_)) { } + + Derived& operator=(BOOST_RV_REF(Derived) x) // Move assign + { + Base::operator=(boost::move(static_cast(x))); + mem_ = boost::move(x.mem_); + return *this; + } + + Derived& operator=(BOOST_COPY_ASSIGN_REF(Derived) x) // Copy assign + { + Base::operator=(static_cast(x)); + mem_ = x.mem_; + return *this; + } + // ... +}; +//] + +//[clone_ptr_def +template +class clone_ptr +{ + private: + // Mark this class copyable and movable + BOOST_COPYABLE_AND_MOVABLE(clone_ptr) + T* ptr; + + public: + // Construction + explicit clone_ptr(T* p = 0) : ptr(p) {} + + // Destruction + ~clone_ptr() { delete ptr; } + + clone_ptr(const clone_ptr& p) // Copy constructor (as usual) + : ptr(p.ptr ? p.ptr->clone() : 0) {} + + clone_ptr& operator=(BOOST_COPY_ASSIGN_REF(clone_ptr) p) // Copy assignment + { + if (this != &p){ + T *tmp_p = p.ptr ? p.ptr->clone() : 0; + delete ptr; + ptr = tmp_p; + } + return *this; + } + + //Move semantics... + clone_ptr(BOOST_RV_REF(clone_ptr) p) //Move constructor + : ptr(p.ptr) { p.ptr = 0; } + + clone_ptr& operator=(BOOST_RV_REF(clone_ptr) p) //Move assignment + { + if (this != &p){ + delete ptr; + ptr = p.ptr; + p.ptr = 0; + } + return *this; + } +}; +//] + +int main() +{ + { + //[copy_clone_ptr + clone_ptr p1(new Derived()); + // ... + clone_ptr p2 = p1; // p2 and p1 each own their own pointer + //] + } + { + //[move_clone_ptr + clone_ptr p1(new Derived()); + // ... + clone_ptr p2 = boost::move(p1); // p2 now owns the pointer instead of p1 + p2 = clone_ptr(new Derived()); // temporary is moved to p2 + } + //] + //[clone_ptr_move_derived + Derived d; + Derived d2(boost::move(d)); + d2 = boost::move(d); + //] + return 0; +} diff --git a/example/doc_construct_forward.cpp b/example/doc_construct_forward.cpp new file mode 100644 index 0000000..07be958 --- /dev/null +++ b/example/doc_construct_forward.cpp @@ -0,0 +1,105 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2009. +// 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. +// +////////////////////////////////////////////////////////////////////////////// + +//[construct_forward_example +#include +#include + +class copyable_only_tester +{ + public: + copyable_only_tester() + { std::cout << "copyable_only_tester()" << std::endl; } + + copyable_only_tester(const copyable_only_tester&) + { std::cout << "copyable_only_tester(const copyable_only_tester&)" << std::endl; } + + copyable_only_tester(int) + { std::cout << "copyable_only_tester(int)" << std::endl; } + + copyable_only_tester(int, double) + { std::cout << "copyable_only_tester(int, double)" << std::endl; } +}; + +class copyable_movable_tester +{ + // move semantics + BOOST_COPYABLE_AND_MOVABLE(copyable_movable_tester) + public: + + copyable_movable_tester() + { std::cout << "copyable_movable_tester()" << std::endl; } + + copyable_movable_tester(int) + { std::cout << "copyable_movable_tester(int)" << std::endl; } + + copyable_movable_tester(BOOST_RV_REF(copyable_movable_tester)) + { std::cout << "copyable_movable_tester(BOOST_RV_REF(copyable_movable_tester))" << std::endl; } + + copyable_movable_tester(const copyable_movable_tester &) + { std::cout << "copyable_movable_tester(const copyable_movable_tester &)" << std::endl; } + + copyable_movable_tester(BOOST_RV_REF(copyable_movable_tester), BOOST_RV_REF(copyable_movable_tester)) + { std::cout << "copyable_movable_tester(BOOST_RV_REF(copyable_movable_tester), BOOST_RV_REF(copyable_movable_tester))" << std::endl; } + + copyable_movable_tester &operator=(BOOST_RV_REF(copyable_movable_tester)) + { std::cout << "copyable_movable_tester & operator=(BOOST_RV_REF(copyable_movable_tester))" << std::endl; + return *this; } + + copyable_movable_tester &operator=(BOOST_COPY_ASSIGN_REF(copyable_movable_tester)) + { std::cout << "copyable_movable_tester & operator=(BOOST_COPY_ASSIGN_REF(copyable_movable_tester))" << std::endl; + return *this; } +}; + +//1 argument +template +void function_construct(BOOST_FWD_REF(MaybeRv) x) +{ MaybeMovable m(boost::forward(x)); } + +//2 argument +template +void function_construct(BOOST_FWD_REF(MaybeRv) x, BOOST_FWD_REF(MaybeRv2) x2) +{ MaybeMovable m(boost::forward(x), boost::forward(x2)); } + +int main() +{ + copyable_movable_tester m; + //move constructor + function_construct(boost::move(m)); + //copy constructor + function_construct(copyable_movable_tester()); + //two rvalue constructor + function_construct(boost::move(m), boost::move(m)); + + copyable_only_tester nm; + //copy constructor (copyable_only_tester has no move ctor.) + function_construct(boost::move(nm)); + //copy constructor + function_construct(nm); + //int constructor + function_construct(int(0)); + //int, double constructor + function_construct(int(0), double(0.0)); + + //Output is: + //copyable_movable_tester() + //copyable_movable_tester(BOOST_RV_REF(copyable_movable_tester)) + //copyable_movable_tester() + //copyable_movable_tester(const copyable_movable_tester &) + //copyable_movable_tester(BOOST_RV_REF(copyable_movable_tester), BOOST_RV_REF(copyable_movable_tester)) + //copyable_only_tester() + //copyable_only_tester(const copyable_only_tester&) + //copyable_only_tester(const copyable_only_tester&) + //copyable_only_tester(int) + //copyable_only_tester(int, double) + return 0; +} +//] diff --git a/example/doc_file_descriptor.cpp b/example/doc_file_descriptor.cpp new file mode 100644 index 0000000..0691ebb --- /dev/null +++ b/example/doc_file_descriptor.cpp @@ -0,0 +1,87 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008-2009. +// 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_descriptor_def + +#include +#include + +class file_descriptor +{ + //<- + int operating_system_open_file(const char *) + { + return 1; + } + + void operating_system_close_file(int) + {} + //-> + int os_descr_; + + private: + BOOST_MOVABLE_BUT_NOT_COPYABLE(file_descriptor) + + public: + explicit file_descriptor(const char *filename = 0) //Constructor + : os_descr_(filename ? operating_system_open_file(filename) : 0) + { if(!os_descr_) throw std::runtime_error("file not found"); } + + ~file_descriptor() //Destructor + { if(!os_descr_) operating_system_close_file(os_descr_); } + + file_descriptor(BOOST_RV_REF(file_descriptor) x) // Move ctor + : os_descr_(x.os_descr_) + { x.os_descr_ = 0; } + + file_descriptor& operator=(BOOST_RV_REF(file_descriptor) x) // Move assign + { + if(!os_descr_) operating_system_close_file(os_descr_); + os_descr_ = x.os_descr_; + x.os_descr_ = 0; + return *this; + } + + bool empty() const { return os_descr_ == 0; } +}; + +//] + +//[file_descriptor_example +#include +#include + +//Remember: 'file_descriptor' is NOT copyable, but it +//can be returned from functions thanks to move semantics +file_descriptor create_file_descriptor(const char *filename) +{ return file_descriptor(filename); } + +int main() +{ + //Open a file obtaining its descriptor, the temporary + //returned from 'create_file_descriptor' is moved to 'fd'. + file_descriptor fd = create_file_descriptor("filename"); + assert(!fd.empty()); + + //Now move fd into a vector + boost::interprocess::vector v; + v.push_back(boost::move(fd)); + + //Check ownership has been transferred + assert(fd.empty()); + assert(!v[0].empty()); + + //Compilation error if uncommented since file_descriptor is not copyable + //and vector copy construction requires value_type's copy constructor: + //boost::interprocess::vector v2(v); + return 0; +} +//] diff --git a/example/doc_how_works.cpp b/example/doc_how_works.cpp new file mode 100644 index 0000000..e2116c5 --- /dev/null +++ b/example/doc_how_works.cpp @@ -0,0 +1,60 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009. +// 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 + +#if !defined(BOOST_NO_RVALUE_REFERENCES) + +int main() +{ + return 0; +} + +#else + +//[how_works_example +#include +#include + +class sink_tester +{ + public: //conversions provided by BOOST_COPYABLE_AND_MOVABLE + operator ::boost::rv&() + { return *static_cast< ::boost::rv* >(this); } + operator const ::boost::rv&() const + { return *static_cast* >(this); } +}; + +//Functions returning different r/lvalue types + sink_tester rvalue() { return sink_tester(); } +const sink_tester const_rvalue() { return sink_tester(); } + sink_tester & lvalue() { static sink_tester lv; return lv; } +const sink_tester & const_lvalue() { static const sink_tester clv = sink_tester(); return clv; } + +//BOOST_RV_REF overload +void sink(::boost::rv &) { std::cout << "non-const rvalue catched" << std::endl; } +//BOOST_COPY_ASSIGN_REF overload +void sink(const ::boost::rv &){ std::cout << "const (r-l)value catched" << std::endl; } +//Overload provided by BOOST_COPYABLE_AND_MOVABLE +void sink(sink_tester &) { std::cout << "non-const lvalue catched" << std::endl; } + +int main() +{ + sink(const_rvalue()); //"const (r-l)value catched" + sink(const_lvalue()); //"const (r-l)value catched" + sink(lvalue()); //"non-const lvalue catched" + sink(rvalue()); //"non-const rvalue catched" + return 0; +} +//] + +#endif + diff --git a/example/doc_move_algorithms.cpp b/example/doc_move_algorithms.cpp new file mode 100644 index 0000000..c9ca065 --- /dev/null +++ b/example/doc_move_algorithms.cpp @@ -0,0 +1,41 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009. +// 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. +// +////////////////////////////////////////////////////////////////////////////// + +//[move_algorithms_example +#include "movable.hpp" +#include +#include + +int main() +{ + const std::size_t ArraySize = 10; + movable movable_array[ArraySize]; + movable movable_array2[ArraySize]; + //move + boost::move(&movable_array2[0], &movable_array2[ArraySize], &movable_array[0]); + assert(movable_array2[0].moved()); + assert(!movable_array[0].moved()); + + //move backward + boost::move_backward(&movable_array[0], &movable_array[ArraySize], &movable_array2[ArraySize]); + assert(movable_array[0].moved()); + assert(!movable_array2[0].moved()); + + //uninitialized_move + boost::aligned_storage< sizeof(movable)*ArraySize + , boost::alignment_of::value>::type storage; + movable *raw_movable = static_cast(static_cast(&storage)); + boost::uninitialized_move(&movable_array2[0], &movable_array2[ArraySize], raw_movable); + assert(movable_array2[0].moved()); + assert(!raw_movable[0].moved()); + return 0; +} +//] diff --git a/example/doc_move_inserter.cpp b/example/doc_move_inserter.cpp new file mode 100644 index 0000000..547cc82 --- /dev/null +++ b/example/doc_move_inserter.cpp @@ -0,0 +1,48 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009. +// 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. +// +////////////////////////////////////////////////////////////////////////////// + +//[move_inserter_example +#include +#include "movable.hpp" +#include + +using namespace ::boost::interprocess; + +typedef list list_t; +typedef list_t::iterator l_iterator; + +template +void test_move_inserter(list_t &l2, MoveInsertIterator mit) +{ + //Create a list with 10 default constructed objects + list l(10); + assert(!l.begin()->moved()); + l2.clear(); + + //Move construct + for(l_iterator itbeg = l.begin(), itend = l.end(); itbeg != itend; ++itbeg){ + *mit = *itbeg; + } + //Check size and status + assert(l2.size() == l.size()); + assert(l.begin()->moved()); + assert(!l2.begin()->moved()); +} + +int main() +{ + list_t l2; + test_move_inserter(l2, boost::back_move_inserter(l2)); + test_move_inserter(l2, boost::front_move_inserter(l2)); + test_move_inserter(l2, boost::move_inserter(l2, l2.end())); + return 0; +} +//] diff --git a/example/doc_move_iterator.cpp b/example/doc_move_iterator.cpp new file mode 100644 index 0000000..d48b93f --- /dev/null +++ b/example/doc_move_iterator.cpp @@ -0,0 +1,39 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009. +// 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. +// +////////////////////////////////////////////////////////////////////////////// + +//[move_iterator_example +#include +#include "movable.hpp" +#include + +int main() +{ + using namespace ::boost::interprocess; + + //Create a vector with 10 default constructed objects + vector v(10); + assert(!v[0].moved()); + + //Move construct all elements in v into v2 + vector v2( boost::make_move_iterator(v.begin()) + , boost::make_move_iterator(v.end())); + assert(v[0].moved()); + assert(!v2[0].moved()); + + //Now move assign all elements from in v2 back into v + v.assign( boost::make_move_iterator(v2.begin()) + , boost::make_move_iterator(v2.end())); + assert(v2[0].moved()); + assert(!v[0].moved()); + + return 0; +} +//] diff --git a/example/movable.hpp b/example/movable.hpp new file mode 100644 index 0000000..89b4397 --- /dev/null +++ b/example/movable.hpp @@ -0,0 +1,49 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009. +// 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_TEST_MOVABLE_HPP +#define BOOST_MOVE_TEST_MOVABLE_HPP + +//[movable_definition +//header file "movable.hpp" +#include + +//A movable class +class movable +{ + BOOST_MOVABLE_BUT_NOT_COPYABLE(movable) + int value_; + + public: + movable() : value_(1){} + + //Move constructor and assignment + movable(BOOST_RV_REF(movable) m) + { value_ = m.value_; m.value_ = 0; } + + movable & operator=(BOOST_RV_REF(movable) m) + { value_ = m.value_; m.value_ = 0; return *this; } + + bool moved() const //Observer + { return value_ == 0; } +}; + +namespace boost{ + +template<> +struct has_nothrow_move +{ + static const bool value = true; +}; + +} //namespace boost{ +//] + +#endif //BOOST_MOVE_TEST_MOVABLE_HPP diff --git a/proj/vc7ide/Move.sln b/proj/vc7ide/Move.sln new file mode 100644 index 0000000..68e086e --- /dev/null +++ b/proj/vc7ide/Move.sln @@ -0,0 +1,140 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "construct_forward_test", "construct_forward_test.vcproj", "{CD57C283-1862-42FE-BF87-B96D3A2A7912}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "move_iterator_test", "move_iterator_test.vcproj", "{C8AD2618-79EB-8612-42FE-2A3AC9667A13}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "move_test", "move_test.vcproj", "{CD57C283-1862-42FE-BF87-B96D3A2A7912}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "move_algorithm_test", "move_algorithm.vcproj", "{C8AD2618-79EB-8612-42FE-2A3AC9667A13}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_clone_ptr", "doc_clone_ptr.vcproj", "{CD57C283-1862-42FE-BF87-B96D3A2A7912}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_file_descriptor", "doc_file_descriptor.vcproj", "{CD57C283-1862-42FE-BF87-B96D3A2A7912}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_move_iterator", "doc_move_iterator.vcproj", "{CD57C283-1862-42FE-BF87-B96D3A2A7912}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_move_inserter", "doc_move_inserter.vcproj", "{CD57C283-1862-42FE-BF87-B96D3A2A7912}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_move_algorithms", "doc_move_algorithms.vcproj", "{CD57C283-1862-42FE-BF87-B96D3A2A7912}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_construct_forward", "doc_construct_forward.vcproj", "{CD57C283-1862-42FE-BF87-B96D3A2A7912}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "back_move_inserter_test", "back_move_inserter_test.vcproj", "{C8AD2618-79EB-8612-42FE-2A3AC9667A13}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "copy_move_optimization_test", "copy_move_optimization.vcproj", "{C8AD2618-79EB-8612-42FE-2A3AC9667A13}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "copy_elision_test_test", "copy_elision_test.vcproj", "{C8AD2618-79EB-8612-42FE-2A3AC9667A13}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_how_works", "doc_how_works.vcproj", "{C7C2F583-4FE2-1862-BF87-BA26D31A7995}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "conversion_test", "conversion_test.vcproj", "{CD57C283-1862-42FE-BF87-B96D3A2A7912}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.ActiveCfg = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.Build.0 = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.ActiveCfg = Release|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.Build.0 = Release|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Debug.ActiveCfg = Debug|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Debug.Build.0 = Debug|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Release.ActiveCfg = Release|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Release.Build.0 = Release|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.ActiveCfg = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.Build.0 = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.ActiveCfg = Release|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.Build.0 = Release|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Debug.ActiveCfg = Debug|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Debug.Build.0 = Debug|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Release.ActiveCfg = Release|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Release.Build.0 = Release|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.ActiveCfg = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.Build.0 = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.ActiveCfg = Release|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.Build.0 = Release|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.ActiveCfg = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.Build.0 = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.ActiveCfg = Release|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.Build.0 = Release|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.ActiveCfg = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.Build.0 = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.ActiveCfg = Release|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.Build.0 = Release|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.ActiveCfg = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.Build.0 = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.ActiveCfg = Release|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.Build.0 = Release|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.ActiveCfg = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.Build.0 = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.ActiveCfg = Release|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.Build.0 = Release|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.ActiveCfg = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.Build.0 = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.ActiveCfg = Release|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.Build.0 = Release|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Debug.ActiveCfg = Debug|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Debug.Build.0 = Debug|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Release.ActiveCfg = Release|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Release.Build.0 = Release|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Debug.ActiveCfg = Debug|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Debug.Build.0 = Debug|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Release.ActiveCfg = Release|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Release.Build.0 = Release|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Debug.ActiveCfg = Debug|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Debug.Build.0 = Debug|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Release.ActiveCfg = Release|Win32 + {C8AD2618-79EB-8612-42FE-2A3AC9667A13}.Release.Build.0 = Release|Win32 + {C7C2F583-4FE2-1862-BF87-BA26D31A7995}.Debug.ActiveCfg = Debug|Win32 + {C7C2F583-4FE2-1862-BF87-BA26D31A7995}.Debug.Build.0 = Debug|Win32 + {C7C2F583-4FE2-1862-BF87-BA26D31A7995}.Release.ActiveCfg = Release|Win32 + {C7C2F583-4FE2-1862-BF87-BA26D31A7995}.Release.Build.0 = Release|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.ActiveCfg = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.Build.0 = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.ActiveCfg = Release|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionItems) = postSolution + ..\..\doc\Jamfile.v2 = ..\..\doc\Jamfile.v2 + ..\..\..\..\boost\move\move.hpp = ..\..\..\..\boost\move\move.hpp + ..\..\doc\move.qbk = ..\..\doc\move.qbk + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/proj/vc7ide/back_move_inserter_test.vcproj b/proj/vc7ide/back_move_inserter_test.vcproj new file mode 100644 index 0000000..17a751f --- /dev/null +++ b/proj/vc7ide/back_move_inserter_test.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/construct_forward_test.vcproj b/proj/vc7ide/construct_forward_test.vcproj new file mode 100644 index 0000000..be11eec --- /dev/null +++ b/proj/vc7ide/construct_forward_test.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/conversion_test.vcproj b/proj/vc7ide/conversion_test.vcproj new file mode 100644 index 0000000..1321c21 --- /dev/null +++ b/proj/vc7ide/conversion_test.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/copy_elision_test.vcproj b/proj/vc7ide/copy_elision_test.vcproj new file mode 100644 index 0000000..9a31cd7 --- /dev/null +++ b/proj/vc7ide/copy_elision_test.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/copy_move_optimization.vcproj b/proj/vc7ide/copy_move_optimization.vcproj new file mode 100644 index 0000000..13ef1a4 --- /dev/null +++ b/proj/vc7ide/copy_move_optimization.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_clone_ptr.vcproj b/proj/vc7ide/doc_clone_ptr.vcproj new file mode 100644 index 0000000..e87a8b8 --- /dev/null +++ b/proj/vc7ide/doc_clone_ptr.vcproj @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_construct_forward.vcproj b/proj/vc7ide/doc_construct_forward.vcproj new file mode 100644 index 0000000..5afea83 --- /dev/null +++ b/proj/vc7ide/doc_construct_forward.vcproj @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_file_descriptor.vcproj b/proj/vc7ide/doc_file_descriptor.vcproj new file mode 100644 index 0000000..2ea9a34 --- /dev/null +++ b/proj/vc7ide/doc_file_descriptor.vcproj @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_how_works.vcproj b/proj/vc7ide/doc_how_works.vcproj new file mode 100644 index 0000000..62363e8 --- /dev/null +++ b/proj/vc7ide/doc_how_works.vcproj @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_move_algorithms.vcproj b/proj/vc7ide/doc_move_algorithms.vcproj new file mode 100644 index 0000000..62e3595 --- /dev/null +++ b/proj/vc7ide/doc_move_algorithms.vcproj @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_move_inserter.vcproj b/proj/vc7ide/doc_move_inserter.vcproj new file mode 100644 index 0000000..8bf944b --- /dev/null +++ b/proj/vc7ide/doc_move_inserter.vcproj @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_move_iterator.vcproj b/proj/vc7ide/doc_move_iterator.vcproj new file mode 100644 index 0000000..1e1370a --- /dev/null +++ b/proj/vc7ide/doc_move_iterator.vcproj @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/move_algorithm.vcproj b/proj/vc7ide/move_algorithm.vcproj new file mode 100644 index 0000000..33d4e5e --- /dev/null +++ b/proj/vc7ide/move_algorithm.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/move_iterator_test.vcproj b/proj/vc7ide/move_iterator_test.vcproj new file mode 100644 index 0000000..49355ee --- /dev/null +++ b/proj/vc7ide/move_iterator_test.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/move_test.vcproj b/proj/vc7ide/move_test.vcproj new file mode 100644 index 0000000..a95ac52 --- /dev/null +++ b/proj/vc7ide/move_test.vcproj @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 new file mode 100644 index 0000000..22b904b --- /dev/null +++ b/test/Jamfile.v2 @@ -0,0 +1,28 @@ +############################################################################## +## +## (C) Copyright Ion Gaztanaga 2008-2009 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) +## +## +############################################################################## +rule test_all +{ + local all_rules = ; + + for local fileb in [ glob *.cpp ] + { + all_rules += [ run $(fileb) + : # additional args + : # test-files + : # requirements + ] ; + } + + return $(all_rules) ; +} + +test-suite move_test : [ test_all r ] +: static +; + diff --git a/test/back_move_inserter.cpp b/test/back_move_inserter.cpp new file mode 100644 index 0000000..27d28f4 --- /dev/null +++ b/test/back_move_inserter.cpp @@ -0,0 +1,61 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2009. +// 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 +#include +#include +#include +#include "../example/movable.hpp" + +template +int move_test() +{ + //Default construct 10 movable objects + Container v(10); + + //Test default constructed value + if(v.begin()->moved()){ + return 1; + } + + //Move values + Container v2; + std::copy(v.begin(), v.end(), boost::back_move_inserter(v2)); + + //Test values have been moved + if(!v.begin()->moved()){ + return 1; + } + + if(v2.size() != 10){ + return 1; + } + + if(v2.begin()->moved()){ + return 1; + } + return 0; +} + +int main() +{ + namespace bi = ::boost::interprocess; + + if(move_test< bi::vector >()){ + return 1; + } + if(move_test< bi::list >()){ + return 1; + } + if(move_test< bi::stable_vector >()){ + return 1; + } + return 0; +} diff --git a/test/construct_forward.cpp b/test/construct_forward.cpp new file mode 100644 index 0000000..bf4c526 --- /dev/null +++ b/test/construct_forward.cpp @@ -0,0 +1,115 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2009-2011. +// 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 +#include +#include "../example/movable.hpp" +#include "../example/copymovable.hpp" +#include + +class non_movable +{ + public: + non_movable() + {} +}; + +template +void catch_test(BOOST_RV_REF(MaybeRvalue) x + #ifdef BOOST_NO_RVALUE_REFERENCES + ,typename ::boost::enable_if< ::boost::has_move_emulation_enabled >::type* = 0 + #endif //BOOST_NO_RVALUE_REFERENCES + ) +{ (void)x;} + +template +void catch_test(BOOST_COPY_ASSIGN_REF(MaybeRvalue) x + #ifdef BOOST_NO_RVALUE_REFERENCES + ,typename ::boost::enable_if< ::boost::has_move_emulation_enabled >::type* = 0 + #endif //BOOST_NO_RVALUE_REFERENCES + ) + +{ (void)x;} + +template +void catch_test(MaybeRvalue &x + #ifdef BOOST_NO_RVALUE_REFERENCES + ,typename ::boost::enable_if< ::boost::has_move_emulation_enabled >::type* = 0 + #endif //BOOST_NO_RVALUE_REFERENCES + ) +{ (void)x;} + + #ifdef BOOST_NO_RVALUE_REFERENCES +template +void catch_test(const MaybeRvalue& x + ,typename ::boost::disable_if< ::boost::has_move_emulation_enabled >::type* = 0 + ) +{ (void)x;} + #endif //BOOST_NO_RVALUE_REFERENCES + +movable create_movable() +{ return movable(); } + +copy_movable create_copy_movable() +{ return copy_movable(); } + +non_movable create_non_movable() +{ return non_movable(); } + + +void catch_test() +{ + movable m; + const movable constm; + catch_test(boost::move(m)); + #ifdef BOOST_CATCH_CONST_RLVALUE + catch_test(create_movable()); + #endif + catch_test(m); + catch_test(constm); + copy_movable cm; + const copy_movable constcm; + catch_test(boost::move(cm)); + catch_test(create_copy_movable()); + catch_test(cm); + catch_test(constcm); + non_movable nm; + const non_movable constnm; + catch_test(boost::move(nm)); + catch_test(create_non_movable()); + catch_test(nm); + catch_test(constnm); +} + +template +void function_construct(BOOST_FWD_REF(MaybeRvalue) x) +{ + //Moves in case Convertible is boost::rv copies otherwise + //For C++0x perfect forwarding + MaybeMovableOnly m(boost::forward(x)); +} + +void forward_test() +{ + movable m; + function_construct(boost::move(m)); +// non_movable nm; +// function_construct(boost::move(nm)); +// const non_movable cnm; +// function_construct(cnm); +} + +int main() +{ + catch_test(); + forward_test(); + return 0; +} diff --git a/test/conversion_test.cpp b/test/conversion_test.cpp new file mode 100644 index 0000000..99157c1 --- /dev/null +++ b/test/conversion_test.cpp @@ -0,0 +1,677 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2010-2011. +// 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 + +#include +#include +#include +#include + + +enum ConstructionType { Copied, Moved, Other }; + +class conversion_source +{ + public: + conversion_source(){} + operator int() const { return 0; } +}; + +class conversion_target +{ + ConstructionType c_type_; + public: + conversion_target(conversion_source) + { c_type_ = Other; } + conversion_target() + { c_type_ = Other; } + conversion_target(const conversion_target &) + { c_type_ = Copied; } + ConstructionType construction_type() const + { return c_type_; } +}; + + +class conversion_target_copymovable +{ + ConstructionType c_type_; + BOOST_COPYABLE_AND_MOVABLE(conversion_target_copymovable) + public: + conversion_target_copymovable() + { c_type_ = Other; } + conversion_target_copymovable(conversion_source) + { c_type_ = Other; } + conversion_target_copymovable(const conversion_target_copymovable &) + { c_type_ = Copied; } + conversion_target_copymovable(BOOST_RV_REF(conversion_target_copymovable) ) + { c_type_ = Moved; } + conversion_target_copymovable &operator=(BOOST_RV_REF(conversion_target_copymovable) ) + { c_type_ = Moved; return *this; } + conversion_target_copymovable &operator=(BOOST_COPY_ASSIGN_REF(conversion_target_copymovable) ) + { c_type_ = Copied; return *this; } + ConstructionType construction_type() const + { return c_type_; } +}; + +class conversion_target_movable +{ + ConstructionType c_type_; + BOOST_MOVABLE_BUT_NOT_COPYABLE(conversion_target_movable) + public: + conversion_target_movable() + { c_type_ = Other; } + conversion_target_movable(conversion_source) + { c_type_ = Other; } + conversion_target_movable(BOOST_RV_REF(conversion_target_movable) ) + { c_type_ = Moved; } + conversion_target_movable &operator=(BOOST_RV_REF(conversion_target_movable) ) + { c_type_ = Moved; return *this; } + ConstructionType construction_type() const + { return c_type_; } +}; + + +template +class container +{ + typename ::boost::aligned_storage::value>::type storage_; + public: + + typedef T * iterator; + typedef const T * const_iterator; + + BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back) + + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator) + + ConstructionType construction_type() const + { return construction_type_impl(typename ::boost::is_class::type()); } + ConstructionType construction_type_impl(::boost::true_type) const + { return reinterpret_cast(storage_).construction_type(); } + ConstructionType construction_type_impl(::boost::false_type) const + { return Copied; } + + iterator begin() { return iterator(0); } + + private: + + template + void priv_push_back(BOOST_MOVE_CATCH_FWD(U) x) + { new (&storage_) T(::boost::forward(x)); } + + template + iterator priv_insert(const_iterator, BOOST_MOVE_CATCH_FWD(U) x) + { new (&storage_) T(::boost::forward(x)); return 0; } +}; + + +int main() +{ + conversion_target_movable a; + conversion_target_movable b(::boost::move(a)); + { + container c; + { + conversion_target x; + c.push_back(x); + assert(c.construction_type() == Copied); + c.insert(c.begin(), x); + assert(c.construction_type() == Copied); + } + { + const conversion_target x; + c.push_back(x); + assert(c.construction_type() == Copied); + c.insert(c.begin(), x); + assert(c.construction_type() == Copied); + } + { + c.push_back(conversion_target()); + assert(c.construction_type() == Copied); + c.insert(c.begin(), conversion_target()); + assert(c.construction_type() == Copied); + } + { + conversion_source x; + c.push_back(x); + assert(c.construction_type() == Copied); + c.insert(c.begin(), x); + assert(c.construction_type() == Copied); + } + { + const conversion_source x; + c.push_back(x); + assert(c.construction_type() == Copied); + c.insert(c.begin(), x); + assert(c.construction_type() == Copied); + } + { + c.push_back(conversion_source()); + assert(c.construction_type() == Copied); + c.insert(c.begin(), conversion_source()); + assert(c.construction_type() == Copied); + } + } + + { + container c; + { + conversion_target_copymovable x; + c.push_back(x); + assert(c.construction_type() == Copied); + c.insert(c.begin(), x); + assert(c.construction_type() == Copied); + } + { + const conversion_target_copymovable x; + c.push_back(x); + assert(c.construction_type() == Copied); + c.insert(c.begin(), x); + assert(c.construction_type() == Copied); + } + { + c.push_back(conversion_target_copymovable()); + assert(c.construction_type() == Moved); + c.insert(c.begin(), conversion_target_copymovable()); + assert(c.construction_type() == Moved); + } + { + conversion_source x; + c.push_back(x); + assert(c.construction_type() == Moved); + c.insert(c.begin(), x); + assert(c.construction_type() == Moved); + } + { + const conversion_source x; + c.push_back(x); + assert(c.construction_type() == Moved); + c.insert(c.begin(), x); + assert(c.construction_type() == Moved); + } + { + c.push_back(conversion_source()); + assert(c.construction_type() == Moved); + c.insert(c.begin(), conversion_source()); + assert(c.construction_type() == Moved); + } + } + { + container c; + //This should not compile + //{ + // conversion_target_movable x; + // c.push_back(x); + // assert(c.construction_type() == Copied); + //} + //{ + // const conversion_target_movable x; + // c.push_back(x); + // assert(c.construction_type() == Copied); + //} + { + c.push_back(conversion_target_movable()); + assert(c.construction_type() == Moved); + c.insert(c.begin(), conversion_target_movable()); + assert(c.construction_type() == Moved); + } + { + conversion_source x; + c.push_back(x); + assert(c.construction_type() == Moved); + c.insert(c.begin(), x); + assert(c.construction_type() == Moved); + } + { + const conversion_source x; + c.push_back(x); + assert(c.construction_type() == Moved); + c.insert(c.begin(), x); + assert(c.construction_type() == Moved); + } + { + c.push_back(conversion_source()); + assert(c.construction_type() == Moved); + c.insert(c.begin(), conversion_source()); + assert(c.construction_type() == Moved); + } + } + { + container c; + { + int x; + c.push_back(x); + assert(c.construction_type() == Copied); + c.insert(c.begin(), c.construction_type()); + assert(c.construction_type() == Copied); + } + { + const int x = 0; + c.push_back(x); + assert(c.construction_type() == Copied); + c.insert(c.begin(), x); + assert(c.construction_type() == Copied); + } + { + c.push_back(int(0)); + assert(c.construction_type() == Copied); + c.insert(c.begin(), int(0)); + assert(c.construction_type() == Copied); + } + { + conversion_source x; + c.push_back(x); + assert(c.construction_type() == Copied); + c.insert(c.begin(), x); + assert(c.construction_type() == Copied); + } + + { + const conversion_source x; + c.push_back(x); + assert(c.construction_type() == Copied); + c.insert(c.begin(), x); + assert(c.construction_type() == Copied); + } + { + c.push_back(conversion_source()); + assert(c.construction_type() == Copied); + c.insert(c.begin(), conversion_source()); + assert(c.construction_type() == Copied); + } + } + + return 0; +} + +/* +#include +#include +#include +#include +#include +#include +#include + + +enum ConstructionType { Default, Copied, Moved, Other }; + +class conversion_source +{ + public: + conversion_source(){} + operator int() const { return 0; } +}; + +class conversion_target +{ + ConstructionType c_type_; + public: + conversion_target(conversion_source) + { c_type_ = Other; } + conversion_target() + { c_type_ = Default; } + conversion_target(const conversion_target &) + { c_type_ = Copied; } + ConstructionType construction_type() const + { return c_type_; } +}; + + +class conversion_target_copymovable +{ + ConstructionType c_type_; + BOOST_COPYABLE_AND_MOVABLE(conversion_target_copymovable) + public: + conversion_target_copymovable() + { c_type_ = Default; } + conversion_target_copymovable(conversion_source) + { c_type_ = Other; } + conversion_target_copymovable(const conversion_target_copymovable &) + { c_type_ = Copied; } + conversion_target_copymovable(BOOST_RV_REF(conversion_target_copymovable) ) + { c_type_ = Moved; } + conversion_target_copymovable &operator=(BOOST_RV_REF(conversion_target_copymovable) ) + { c_type_ = Moved; return *this; } + conversion_target_copymovable &operator=(BOOST_COPY_ASSIGN_REF(conversion_target_copymovable) ) + { c_type_ = Copied; return *this; } + ConstructionType construction_type() const + { return c_type_; } +}; + +class conversion_target_movable +{ + ConstructionType c_type_; + BOOST_MOVABLE_BUT_NOT_COPYABLE(conversion_target_movable) + public: + conversion_target_movable() + { c_type_ = Default; } + conversion_target_movable(conversion_source) + { c_type_ = Other; } + conversion_target_movable(BOOST_RV_REF(conversion_target_movable) ) + { c_type_ = Moved; } + conversion_target_movable &operator=(BOOST_RV_REF(conversion_target_movable) ) + { c_type_ = Moved; return *this; } + ConstructionType construction_type() const + { return c_type_; } +}; + +struct not_a_type; + +#if defined(BOOST_NO_RVALUE_REFERENCES) +#define BOOST_MOVE_CATCH_CONST(U) \ + typename ::boost::mpl::if_< ::boost::is_class, BOOST_CATCH_CONST_RLVALUE(U), const U &>::type +#define BOOST_MOVE_CATCH_RVALUE(U)\ + typename ::boost::mpl::if_< ::boost::is_class, BOOST_RV_REF(T), not_a_type>::type +#else +#define BOOST_MOVE_CATCH_CONST(U) BOOST_CATCH_CONST_RLVALUE(U) +#define BOOST_MOVE_CATCH_RVALUE(U) BOOST_RV_REF(U) +#endif + +// BEGIN JLH additional definitions... + +template< class T > struct remove_const_remove_reference { typedef T type; }; +template< class T > struct remove_const_remove_reference< const T > : remove_const_remove_reference { }; +template< class T > struct remove_const_remove_reference< volatile T > : remove_const_remove_reference { }; +template< class T > struct remove_const_remove_reference< const volatile T > : remove_const_remove_reference { }; +template< class T > struct remove_const_remove_reference< T& > : remove_const_remove_reference { }; +template< class T > struct remove_const_remove_reference< boost::rv > : remove_const_remove_reference { }; + +template< class T > struct add_reference_add_const { typedef T const & type; }; +template< class T > struct add_reference_add_const< T& > { typedef T& type; }; + +template< class T, class U > +struct is_same_sans_const_sans_reference + : boost::is_same< + typename remove_const_remove_reference::type, + typename remove_const_remove_reference::type + > +{ }; + +template< class T > struct add_lvalue_reference { 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_lvalue_reference< T& > { typedef T& type; }; +template< class T > struct add_lvalue_reference< boost::rv > { typedef T& type; }; +template< class T > struct add_lvalue_reference< const boost::rv > { typedef const T& type; }; +template< class T > struct add_lvalue_reference< volatile boost::rv > { typedef volatile T& type; }; +template< class T > struct add_lvalue_reference< const volatile boost::rv > { typedef const volatile T& type; }; +template< class T > struct add_lvalue_reference< boost::rv& > { typedef T& type; }; +template< class T > struct add_lvalue_reference< const boost::rv& > { typedef const T& type; }; +template< class T > struct add_lvalue_reference< volatile boost::rv& > { typedef volatile T& type; }; +template< class T > struct add_lvalue_reference< const volatile boost::rv& > { typedef const volatile T& type; }; + +template< class T > struct remove_rvalue_reference { typedef T type; }; +template< class T > struct remove_rvalue_reference< boost::rv > { typedef T type; }; +template< class T > struct remove_rvalue_reference< const boost::rv > { typedef T type; }; +template< class T > struct remove_rvalue_reference< volatile boost::rv > { typedef T type; }; +template< class T > struct remove_rvalue_reference< const volatile boost::rv > { typedef T type; }; +template< class T > struct remove_rvalue_reference< boost::rv& > { typedef T type; }; +template< class T > struct remove_rvalue_reference< const boost::rv& > { typedef T type; }; +template< class T > struct remove_rvalue_reference< volatile boost::rv& > { typedef T type; }; +template< class T > struct remove_rvalue_reference< const volatile boost::rv& > { typedef T type; }; + +template< class T > +struct add_rvalue_reference + : boost::mpl::if_< + boost::has_move_emulation_enabled, + boost::rv&, + T + > +{ }; + +template< class T > +struct remove_crv + : remove_rvalue_reference +{ }; +template< class T > +struct remove_crv< const T > + : remove_rvalue_reference +{ }; + +template< class T > +inline typename add_lvalue_reference::type +as_lvalue(T& x) +{ return x; } + +// END JLH additional definitions... + +template +class container +{ + typename ::boost::aligned_storage::value>::type storage_; + public: + + ConstructionType construction_type() const + { return construction_type_impl(typename ::boost::is_class::type()); } + ConstructionType construction_type_impl(::boost::true_type) const + { return reinterpret_cast(storage_).construction_type(); } + ConstructionType construction_type_impl(::boost::false_type) const + { return Copied; } + +#if 0 + + // Ion's original implementation + + void push_back(BOOST_MOVE_CATCH_CONST(T) x) + { return priv_push_back(static_cast(x)); } + + void push_back(BOOST_MOVE_CATCH_RVALUE(T) x) + { return priv_push_back(::boost::move(x)); } + + //Tricks for C++03 + #if defined(BOOST_NO_RVALUE_REFERENCES) + void push_back(T &x) + { priv_push_back(const_cast(x)); } + + template + typename ::boost::enable_if_c + < ::boost::is_class::value && + ::boost::is_same::value && + !::boost::has_move_emulation_enabled::value + >::type + push_back(const U &u) + { return priv_push_back(u); } + + template + typename ::boost::enable_if_c + < ::boost::is_class::value && + !::boost::is_same::value && + !::boost::move_detail::is_rv::value + >::type + push_back(const U &u) + { + T t(u); + priv_push_back(::boost::move(t)); + } + + #endif + + private: + template + void priv_push_back(BOOST_FWD_REF(U) x) + { new (&storage_) T(::boost::forward(x)); } + +#else // #if 0|1 + + // JLH's current implementation (roughly; only showing C++03 here) + + template< class U > + typename boost::disable_if< + is_same_sans_const_sans_reference + >::type + push_back(const U& x) { priv_push_back(as_lvalue(x)); } + template< class U > + void + push_back(U& x) { priv_push_back(x); } + + typedef typename add_reference_add_const< + typename add_rvalue_reference::type + >::type rv_param_type; + + void + push_back(rv_param_type x) { priv_push_back(x); } +private: + template< class U > + void + priv_push_back(U& x) { new (&storage_) T(x); } + +#endif // #if 0|1 +}; + + +int main() +{ + conversion_target_movable a; + conversion_target_movable b(::boost::move(a)); + { + container c; + { + conversion_target x; + c.push_back(x); + assert(c.construction_type() == Copied); + } + { + const conversion_target x; + c.push_back(x); + assert(c.construction_type() == Copied); + } + { + c.push_back(conversion_target()); + assert(c.construction_type() == Copied); + } + { + conversion_source x; + c.push_back(x); + //assert(c.construction_type() == Copied); + assert(c.construction_type() == Other); + } + { + const conversion_source x; + c.push_back(x); + //assert(c.construction_type() == Copied); + assert(c.construction_type() == Other); + } + { + c.push_back(conversion_source()); + //assert(c.construction_type() == Copied); + assert(c.construction_type() == Other); + } + } + + { + container c; + { + conversion_target_copymovable x; + c.push_back(x); + assert(c.construction_type() == Copied); + } + { + const conversion_target_copymovable x; + c.push_back(x); + assert(c.construction_type() == Copied); + } + { + c.push_back(conversion_target_copymovable()); + assert(c.construction_type() == Moved); + } + { + conversion_source x; + c.push_back(x); + //assert(c.construction_type() == Moved); + assert(c.construction_type() == Other); + } + { + const conversion_source x; + c.push_back(x); + //assert(c.construction_type() == Moved); + assert(c.construction_type() == Other); + } + { + c.push_back(conversion_source()); + //assert(c.construction_type() == Moved); + assert(c.construction_type() == Other); + } + } + { + container c; + //This should not compile + //{ + // conversion_target_movable x; + // c.push_back(x); + // assert(c.construction_type() == Copied); + //} + //{ + // const conversion_target_movable x; + // c.push_back(x); + // assert(c.construction_type() == Copied); + //} + { + c.push_back(conversion_target_movable()); + assert(c.construction_type() == Moved); + } + { + conversion_source x; + c.push_back(x); + //assert(c.construction_type() == Moved); + assert(c.construction_type() == Other); + } + { + const conversion_source x; + c.push_back(x); + //assert(c.construction_type() == Moved); + assert(c.construction_type() == Other); + } + { + c.push_back(conversion_source()); + //assert(c.construction_type() == Moved); + assert(c.construction_type() == Other); + } + } + { + container c; + { + int x; + c.push_back(x); + assert(c.construction_type() == Copied); + } + { + const int x = 0; + c.push_back(x); + assert(c.construction_type() == Copied); + } + { + c.push_back(int(0)); + assert(c.construction_type() == Copied); + } + { + conversion_source x; + c.push_back(x); + assert(c.construction_type() == Copied); + } + + { + const conversion_source x; + c.push_back(x); + assert(c.construction_type() == Copied); + } + { + c.push_back(conversion_source()); + assert(c.construction_type() == Copied); + } + } + + return 0; +} + +*/ \ No newline at end of file diff --git a/test/copy_elision_test.cpp b/test/copy_elision_test.cpp new file mode 100644 index 0000000..01bf212 --- /dev/null +++ b/test/copy_elision_test.cpp @@ -0,0 +1,170 @@ +// Copyright David Abrahams 2009. 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) + +#include + +#ifdef NO_MOVE +# undef BOOST_COPY_ASSIGN_REF +# define BOOST_COPY_ASSIGN_REF(X) X const& +# undef BOOST_COPYABLE_AND_MOVABLE +# define BOOST_COPYABLE_AND_MOVABLE(X) +# define MOVE(x) (x) +#else +#include +# define MOVE(x) boost::move(x) +#endif + +struct X +{ + X() : id(instances++) + { + std::cout << "X" << id << ": construct\n"; + } + + X(X const& rhs) : id(instances++) + { + std::cout << "X" << id << ": <- " << "X" << rhs.id << ": **copy**\n"; + ++copies; + } + + // This particular test doesn't exercise assignment, but for + // completeness: + X& operator=(BOOST_COPY_ASSIGN_REF(X) rhs) + { + std::cout << "X" << id << ": <- " << "X" << rhs.id << ": assign\n"; + return *this; + } + +#ifndef NO_MOVE + X& operator=(BOOST_RV_REF(X) rhs) + { + std::cout << "X" << id << ": <- " << "X" << rhs.id << ": move assign\n"; + return *this; + } + + X(BOOST_RV_REF(X) rhs) : id(instances++) + { + std::cout << "X" << id << ": <- " << "X" << rhs.id << ": ..move construct..\n"; + ++copies; + } +#endif + + ~X() { std::cout << "X" << id << ": destroy\n"; } + + unsigned id; + + static unsigned copies; + static unsigned instances; + + BOOST_COPYABLE_AND_MOVABLE(X) +}; + +unsigned X::copies = 0; +unsigned X::instances = 0; + +#define CHECK_COPIES( stmt, min, max, comment ) \ +{ \ + unsigned const old_copies = X::copies; \ + \ + std::cout << "\n" comment "\n" #stmt "\n===========\n"; \ + { \ + stmt; \ + } \ + unsigned const n = X::copies - old_copies; \ + if (n > max) \ + std::cout << "*** max is too low or compiler is buggy ***\n"; \ + if (n < min) \ + std::cout << "*** min is too high or compiler is buggy ***\n"; \ + \ + std::cout << "-----------\n" \ + << n << "/" << max \ + << " possible copies/moves made\n" \ + << max - n << "/" << max - min \ + << " possible elisions performed\n\n"; \ + \ + if (n > min) \ + std::cout << "*** " << n - min \ + << " possible elisions missed! ***\n"; \ +} + +struct trace +{ + trace(char const* name) + : name(name) + { + std::cout << "->: " << name << "\n"; + } + + ~trace() + { + std::cout << "<-: " << name << "\n"; + } + + char const* name; +}; + +void sink(X a) +{ + trace t("sink"); +} + +X nrvo_source() +{ + trace t("nrvo_source"); + X a; + return a; +} + +X urvo_source() +{ + trace t("urvo_source"); + return X(); +} + +X identity(X a) +{ + trace t("identity"); + return a; +} + +X lvalue_; +X& lvalue() +{ + return lvalue_; +} +typedef X rvalue; + +X ternary( bool y ) +{ + X a, b; + return MOVE(y?a:b); +} + +int main(int argc, char* argv[]) +{ + (void)argv; + // Double parens prevent "most vexing parse" + CHECK_COPIES( X a(( lvalue() )), 1, 1, "Direct initialization from lvalue"); + CHECK_COPIES( X a(( rvalue() )), 0, 1, "Direct initialization from rvalue"); + + CHECK_COPIES( X a = lvalue(), 1, 1, "Copy initialization from lvalue" ); + CHECK_COPIES( X a = rvalue(), 0, 1, "Copy initialization from rvalue" ); + + CHECK_COPIES( sink( lvalue() ), 1, 1, "Pass lvalue by value" ); + CHECK_COPIES( sink( rvalue() ), 0, 1, "Pass rvalue by value" ); + + CHECK_COPIES( nrvo_source(), 0, 1, "Named return value optimization (NRVO)" ); + CHECK_COPIES( urvo_source(), 0, 1, "Unnamed return value optimization (URVO)" ); + + // Just to prove these things compose properly + CHECK_COPIES( X a(urvo_source()), 0, 2, "Return value used as ctor arg" ); + + // Expect to miss one possible elision here + CHECK_COPIES( identity( rvalue() ), 0, 2, "Return rvalue passed by value" ); + + // Expect to miss an elision in at least one of the following lines + CHECK_COPIES( X a = ternary( argc == 1000 ), 0, 2, "Return result of ternary operation" ); + CHECK_COPIES( X a = ternary( argc != 1000 ), 0, 2, "Return result of ternary operation again" ); + return 0; +} diff --git a/test/copy_move_optimization.cpp b/test/copy_move_optimization.cpp new file mode 100644 index 0000000..10a0f20 --- /dev/null +++ b/test/copy_move_optimization.cpp @@ -0,0 +1,105 @@ +//We need to declare: +// +//2 conversions: rv & and const rv & +//1 rv & constructor: move constructor +//1 const rv & constructor: copy constructor +//1 T & constructor: copy constructor +// +//Optimization: +//Since RVO is better than move-construction, +//avoid copy constructor overloading. +#include +#include + +bool moved = false; + +class obj +{ + BOOST_COPYABLE_AND_MOVABLE(obj) + public: + + obj() + { + std::cout << "constructing obj" << "\n"; + } + + ~obj() + {} + + obj(const obj &) + { + std::cout << "copy construct from const obj" << "\n"; + } + + // copy construct from movable object (non-const rvalue, explicitly moved lvalue) + obj(BOOST_RV_REF(obj)) + { + std::cout << "move construct from movable rvalue" << "\n"; + } + + obj& operator =(BOOST_COPY_ASSIGN_REF(obj)) + { + std::cout << "copy assign from const obj" << "\n"; + return *this; + } + + obj& operator =(BOOST_RV_REF(obj)) + { + std::cout << "move assign from movable rvalue" << "\n"; + return *this; + } +}; + + +obj rvalue_func() { return obj(); } +const obj const_rvalue_func() { return obj(); } +obj& lvalue_func() { static obj o; return o; } +const obj& const_lvalue_func() { static obj o; return o; } + +obj produce() { return obj(); } + +void consume(obj){} + +int main() +{ + { consume(produce()); } + { obj o = produce(); } + { obj o(produce()); } + { + obj o1(rvalue_func()); + obj o2 = const_rvalue_func(); + obj o3 = lvalue_func(); + obj o4 = const_lvalue_func(); + // can't explicitly move temporaries + //obj o5 = boost::move(rvalue_func()); + obj o5; + //Maybe missed optimization: copied + o5 = rvalue_func(); + //Explicit forward works OK and optimized + o5 = boost::forward(rvalue_func()); + + obj o7 = boost::move(lvalue_func()); + obj o8 = boost::move(const_lvalue_func()); + + obj o; + o = rvalue_func(); + o = const_rvalue_func(); + o = lvalue_func(); + o = const_lvalue_func(); + // can't explicitly move temporaries + //o = boost::move(rvalue_func()); + o = boost::forward(rvalue_func()); + o = boost::move(const_rvalue_func()); + o = boost::move(lvalue_func()); + o = boost::move(const_lvalue_func()); + } + return 0; +} + +//We need to declare: +// +//2 conversions: rv & and const rv & +//1 rv & constructor: move constructor +//1 const rv & constructor: copy constructor +//1 T & constructor: copy constructor + diff --git a/test/move.cpp b/test/move.cpp new file mode 100644 index 0000000..e3e3790 --- /dev/null +++ b/test/move.cpp @@ -0,0 +1,114 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2009. +// 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 +#include "../example/movable.hpp" +#include + +movable function(movable m) +{ + return movable(boost::move(m)); +} + +movable functionr(BOOST_RV_REF(movable) m) +{ + return movable(boost::move(m)); +} + +movable function2(movable m) +{ + return boost::move(m); +} + +BOOST_RV_REF(movable) function2r(BOOST_RV_REF(movable) m) +{ + return boost::move(m); +} + +movable move_return_function2 () +{ + return movable(); +} + +movable move_return_function () +{ + movable m; + return (boost::move(m)); +} + + +//Catch by value +void function_value(movable) +{} + +//Catch by reference +void function_ref(const movable &) +{} + +//Catch by reference +void function_ref(BOOST_RV_REF(movable)) +{} + +struct copyable +{}; + +movable create_movable() +{ return movable(); } +int main() +{ + #if defined(BOOST_NO_RVALUE_REFERENCES) + BOOST_STATIC_ASSERT((boost::has_nothrow_move::value == true)); + BOOST_STATIC_ASSERT((boost::has_nothrow_move::value == false)); + BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled::value == false)); + BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled::value == false)); + BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled::value == false)); + BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled::value == false)); + BOOST_STATIC_ASSERT((boost::has_move_emulation_enabled::value == false)); + #endif + + { + movable m; + movable m2(boost::move(m)); + movable m3(function(movable(boost::move(m2)))); + movable m4(function(boost::move(m3))); + } + { + movable m; + movable m2(boost::move(m)); + movable m3(functionr(movable(boost::move(m2)))); + movable m4(functionr(boost::move(m3))); + } + { + movable m; + movable m2(boost::move(m)); + movable m3(function2(movable(boost::move(m2)))); + movable m4(function2(boost::move(m3))); + } + { + movable m; + movable m2(boost::move(m)); + movable m3(function2r(movable(boost::move(m2)))); + movable m4(function2r(boost::move(m3))); + } + { + movable m; + movable m2(boost::move(m)); + movable m3(move_return_function()); + } + { + movable m; + movable m2(boost::move(m)); + movable m3(move_return_function2()); + } + //limitations_test(); + + return 0; +} diff --git a/test/move_algorithm.cpp b/test/move_algorithm.cpp new file mode 100644 index 0000000..86db155 --- /dev/null +++ b/test/move_algorithm.cpp @@ -0,0 +1,55 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2009. +// 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 +#include +#include "../example/movable.hpp" + +int main() +{ + namespace bi = ::boost::interprocess; + //Default construct 10 movable objects + bi::vector v(10); + bi::vector v2(10); + + //Move to v2 + boost::move(v.begin(), v.end(), v2.begin()); + + //Test values have been moved + if(!v[0].moved()){ + return 1; + } + + if(v2.size() != 10){ + return 1; + } + + if(v2[0].moved()){ + return 1; + } + + //Move to v again + boost::move_backward(v2.begin(), v2.end(), v.end()); + + //Test values have been moved + if(!v2[0].moved()){ + return 1; + } + + if(v.size() != 10){ + return 1; + } + + if(v[0].moved()){ + return 1; + } + + return 0; +} diff --git a/test/move_iterator.cpp b/test/move_iterator.cpp new file mode 100644 index 0000000..05a524b --- /dev/null +++ b/test/move_iterator.cpp @@ -0,0 +1,104 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2009. +// 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 +#include +#include "../example/movable.hpp" + +int main() +{ + namespace bi = ::boost::interprocess; + //Default construct 10 movable objects + bi::vector v(10); + + //Test default constructed value + if(v[0].moved()){ + return 1; + } + + //Move values + bi::vector v2 + (boost::make_move_iterator(v.begin()), boost::make_move_iterator(v.end())); + + //Test values have been moved + if(!v[0].moved()){ + return 1; + } + + if(v2.size() != 10){ + return 1; + } + + //Move again + v.assign(boost::make_move_iterator(v2.begin()), boost::make_move_iterator(v2.end())); + + //Test values have been moved + if(!v2[0].moved()){ + return 1; + } + + if(v[0].moved()){ + return 1; + } + + return 0; +} + +/* +#include + + +class copy_movable +{ + BOOST_COPYABLE_AND_MOVABLE(copy_movable) + int value_; + + public: + copy_movable() : value_(1){} + + //Move constructor and assignment + copy_movable(BOOST_RV_REF(copy_movable) m) + { value_ = m.value_; m.value_ = 0; } + + copy_movable(const copy_movable &m) + { value_ = m.value_; } + + copy_movable & operator=(BOOST_RV_REF(copy_movable) m) + { value_ = m.value_; m.value_ = 0; return *this; } + + copy_movable & operator=(BOOST_COPY_ASSIGN_REF(copy_movable) m) + { value_ = m.value_; return *this; } + + bool moved() const //Observer + { return value_ == 0; } +}; + +struct copy_movable_wrapper +{ + copy_movable cm; +}; + +copy_movable produce() +{ return copy_movable(); } + + +int main() +{ + copy_movable cm; + cm = produce(); + + const copy_movable_wrapper cmw; + copy_movable_wrapper cmw2; + cmw2 = cmw; + + return 0; +} +*/ \ No newline at end of file From 01e16750d4f772ca869962316580de17840dc22b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 3 Apr 2011 09:50:26 +0000 Subject: [PATCH 4/8] Move was detecting clang as an old GCC and applying old-style rvalue-references. [SVN r70924] --- include/boost/move/move.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/move/move.hpp b/include/boost/move/move.hpp index bc1be1e..1d6b3d5 100644 --- a/include/boost/move/move.hpp +++ b/include/boost/move/move.hpp @@ -208,7 +208,9 @@ struct is_base_of #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 5) +#ifndef BOOST_CLANG #define BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES +#endif #else From 1ff1ef8e42d21aa8de15853dd2e38da85011f6f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 28 Aug 2011 09:40:49 +0000 Subject: [PATCH 5/8] Code cleanup [SVN r74097] --- include/boost/move/move.hpp | 1081 ++++++++++++++++++----------------- 1 file changed, 556 insertions(+), 525 deletions(-) diff --git a/include/boost/move/move.hpp b/include/boost/move/move.hpp index 1d6b3d5..40c5c2c 100644 --- a/include/boost/move/move.hpp +++ b/include/boost/move/move.hpp @@ -15,589 +15,607 @@ #ifndef BOOST_MOVE_MOVE_HPP #define BOOST_MOVE_MOVE_HPP +/// @cond + #include + +#ifdef BOOST_MSVC + #ifndef _CRT_SECURE_NO_DEPRECATE + #define BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE + #define _CRT_SECURE_NO_DEPRECATE + #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 -#ifndef BOOST_MOVE_AVOID_BOOST_DEPENDENCIES -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif //#ifdef BOOST_MOVE_AVOID_BOOST_DEPENDENCIES -/// @cond +//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 + #include -#ifdef BOOST_MOVE_AVOID_BOOST_DEPENDENCIES -#define BOOST_MOVE_MPL_NS ::boost::move_detail -#define BOOST_MOVE_BOOST_NS ::boost::move_detail + #define BOOST_MOVE_MPL_NS ::boost::mpl + #define BOOST_MOVE_BOOST_NS ::boost #else -#define BOOST_MOVE_MPL_NS ::boost::mpl -#define BOOST_MOVE_BOOST_NS ::boost -#endif + #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 { + 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 ) + //if_ + template + struct if_c { - return reinterpret_cast( - &const_cast(reinterpret_cast(v))); + 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 T * addressof( T & v ) + { + return ::boost::move_detail::addressof_impl::f + ( ::boost::move_detail::addr_impl_ref( v ), 0 ); } - static inline T * f( T * v, int ) - { return v; } -}; + /* + typedef char one; + struct two {one _[2];}; -template T * addressof( T & v ) -{ - return ::boost::move_detail::addressof_impl::f - ( ::boost::move_detail::addr_impl_ref( v ), 0 ); -} + template + struct is_base_of_host + { + operator B*() const; + operator D*(); + }; -/* -typedef char one; -struct two {one _[2];}; + template + struct is_base_of + { + typedef char yes; + class no { char dummy[2]; }; -template -struct is_base_of_host -{ - operator B*() const; - operator D*(); -}; + template + static yes check(D*, T); + static no check(B*, int); -template -struct is_base_of -{ - typedef char yes; - class no { char dummy[2]; }; + static const bool value = sizeof(check(is_base_of_host(), int())) == sizeof(yes); + }; + */ - template - static yes check(D*, T); - static no check(B*, int); - - static const bool value = sizeof(check(is_base_of_host(), int())) == sizeof(yes); -}; -*/ - -} //namespace move_detail { -} //namespace boost { + } //namespace move_detail { + } //namespace boost { #endif //BOOST_MOVE_AVOID_BOOST_DEPENDENCIES -/// @endcond - +//Compiler workaround detection #if !defined(BOOST_NO_RVALUE_REFERENCES) -#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 5) - -#ifndef BOOST_CLANG -#define BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES -#endif - -#else - -#if defined(_MSC_VER) && (_MSC_VER == 1600) -#define BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG -#endif - -#endif + #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 5) + //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 #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED) -#ifdef __GNUC__ -# define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS __attribute__((__may_alias__)) -#else -# define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS -#endif + //Move emulation rv breaks standard aliasing rules so add workarounds for some compilers + #ifdef __GNUC__ + #define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS __attribute__((__may_alias__)) + #else + #define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS + #endif -namespace boost { + namespace boost { -////////////////////////////////////////////////////////////////////////////// -// -// struct rv -// -////////////////////////////////////////////////////////////////////////////// -template -class rv : public T -{ - rv(); - ~rv(); - rv(rv const&); - void operator=(rv const&); -} BOOST_MOVE_ATTRIBUTE_MAY_ALIAS; + ////////////////////////////////////////////////////////////////////////////// + // + // struct rv + // + ////////////////////////////////////////////////////////////////////////////// + template + class rv : public T + { + rv(); + ~rv(); + rv(rv const&); + void operator=(rv const&); + } BOOST_MOVE_ATTRIBUTE_MAY_ALIAS; -////////////////////////////////////////////////////////////////////////////// -// -// move_detail::is_rv -// -////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// + // + // move_detail::is_rv + // + ////////////////////////////////////////////////////////////////////////////// -namespace move_detail { + namespace move_detail { -template -struct is_rv - : BOOST_MOVE_BOOST_NS::integral_constant -{}; + 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< rv > + : BOOST_MOVE_BOOST_NS::integral_constant + {}; -template -struct is_rv< const rv > - : BOOST_MOVE_BOOST_NS::integral_constant -{}; + template + struct is_rv< const rv > + : BOOST_MOVE_BOOST_NS::integral_constant + {}; -} //namespace move_detail { + } //namespace move_detail { -////////////////////////////////////////////////////////////////////////////// -// -// has_move_emulation_enabled -// -////////////////////////////////////////////////////////////////////////////// -template -struct has_move_emulation_enabled - : BOOST_MOVE_BOOST_NS::is_convertible< T, ::boost::rv& > -{}; + ////////////////////////////////////////////////////////////////////////////// + // + // 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_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< ::boost::rv > + : BOOST_MOVE_BOOST_NS::integral_constant + {}; -template -struct has_nothrow_move - : public BOOST_MOVE_BOOST_NS::integral_constant -{}; + template + struct has_nothrow_move + : public BOOST_MOVE_BOOST_NS::integral_constant + {}; -////////////////////////////////////////////////////////////////////////////// -// -// move() -// -////////////////////////////////////////////////////////////////////////////// -template -typename BOOST_MOVE_BOOST_NS::disable_if, T&>::type move(T& x) -{ - return x; -} + ////////////////////////////////////////////////////////////////////////////// + // + // move() + // + ////////////////////////////////////////////////////////////////////////////// + template + typename BOOST_MOVE_BOOST_NS::disable_if, T&>::type move(T& x) + { + return x; + } -template -typename BOOST_MOVE_BOOST_NS::enable_if, rv&>::type move(T& x) -{ - return *static_cast* >(BOOST_MOVE_BOOST_NS::addressof(x)); -} + template + typename BOOST_MOVE_BOOST_NS::enable_if, rv&>::type move(T& x) + { + return *static_cast* >(BOOST_MOVE_BOOST_NS::addressof(x)); + } -template -typename BOOST_MOVE_BOOST_NS::enable_if, rv&>::type move(rv& x) -{ - return x; -} + template + 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(TYPE)\ + ::boost::rv< TYPE >& \ + // -#define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ - ::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_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ + ::boost::rv< TYPE >& \ + // -#define BOOST_FWD_REF(TYPE)\ - const TYPE & \ -// + #define BOOST_FWD_REF(TYPE)\ + const TYPE & \ + // -#define BOOST_CATCH_CONST_RLVALUE(TYPE)\ - const ::boost::rv< 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(TYPE)\ + const ::boost::rv< TYPE >& \ + // -#define BOOST_MOVE_COPY_ASSIGN_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ - const ::boost::rv< TYPE >& \ -// + #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 >& \ -// + #define BOOST_MOVE_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ + const ::boost::rv< TYPE >& \ + // -////////////////////////////////////////////////////////////////////////////// -// -// forward() -// -////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// + // + // forward() + // + ////////////////////////////////////////////////////////////////////////////// -template -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 + 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 -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; -} + template + 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_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 -// -////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// + // + // 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(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:\ -// + #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 + } //namespace boost #else //BOOST_NO_RVALUE_REFERENCES -#include + namespace boost{ -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 + {}; -//! By default this traits returns false. Classes with non-thworing move construction -//! 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{ -////////////////////////////////////////////////////////////////////////////// -// -// move -// -////////////////////////////////////////////////////////////////////////////// + #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 inline + 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 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 inline -rvalue_reference move (input_reference); + #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 inline output_reference forward(input_reference); + #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) -#else //BOOST_MOVE_DOXYGEN_INVOKED + //Old move approach, lvalues could bind to rvalue references -#if defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) + template inline + T&& forward (typename BOOST_MOVE_MPL_NS::identity::type&& t) + { return t; } -//Old move approach, lvalues could bind to rvalue references -template inline -typename remove_reference::type && move(T&& t) -{ return t; } + #else //Old move -#else //Old move + //Implementation #5 from N2951, thanks to Howard Hinnant -template inline -typename remove_reference::type && move(T&& t) -{ return static_cast::type &&>(t); } + 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 //Old move + #endif //BOOST_MOVE_DOXYGEN_INVOKED -#endif //BOOST_MOVE_DOXYGEN_INVOKED + } //namespace boost { + #endif //#if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE) -////////////////////////////////////////////////////////////////////////////// -// -// forward -// -////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// + // + // BOOST_ENABLE_MOVE_EMULATION + // + ////////////////////////////////////////////////////////////////////////////// + ///@cond -#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 inline output_reference forward(input_reference); + #define BOOST_ENABLE_MOVE_EMULATION(TYPE)\ + typedef int boost_move_emulation_t; + \ + // -#else + /// @endcond -#if defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES) + //! 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 &);\ + // -//Old move approach, lvalues could bind to rvalue references + //! 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)\ + // -template inline -T&& forward (typename BOOST_MOVE_MPL_NS::identity::type&& t) -{ return t; } + /// @cond -#else //Old move + #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ + TYPE && \ + // -//Implementation #5 from N2951, thanks to Howard Hinnant + #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ + TYPE && \ + // -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); } + /// @endcond -#endif //Old move + //!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 && \ + // -#endif //BOOST_MOVE_DOXYGEN_INVOKED + //!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 & \ + // -////////////////////////////////////////////////////////////////////////////// -// -// BOOST_ENABLE_MOVE_EMULATION -// -////////////////////////////////////////////////////////////////////////////// + /// @cond -///@cond + #define BOOST_COPY_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ + const TYPE & \ + // -#define BOOST_ENABLE_MOVE_EMULATION(TYPE)\ - typedef int boost_move_emulation_t; -\ -// + #define BOOST_COPY_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ + TYPE& \ + // -/// @endcond + /// @endcond -//! 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 is used to implement portable perfect forwarding + //! as explained in the documentation. + #define BOOST_FWD_REF(TYPE)\ + 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)\ -// + /// @cond -/// @cond + #define BOOST_CATCH_CONST_RLVALUE(TYPE)\ + const TYPE & \ + // -#define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ - TYPE && \ -// - -#define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ - TYPE && \ -// - -/// @endcond - -//!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 copy -//!assignment for classes marked as BOOST_COPYABLE_AND_MOVABLE. -#define BOOST_COPY_ASSIGN_REF(TYPE)\ - const TYPE & \ -// - -/// @cond - -#define BOOST_COPY_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ - const TYPE & \ -// - -#define BOOST_COPY_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ - TYPE& \ -// - -/// @endcond - -//! This macro is used to implement portable perfect forwarding -//! as explained in the documentation. -#define BOOST_FWD_REF(TYPE)\ - TYPE && \ -// - -/// @cond - -#define BOOST_CATCH_CONST_RLVALUE(TYPE)\ - const TYPE & \ -// - -/// @endcond - -} //namespace boost { + /// @endcond #endif //BOOST_NO_RVALUE_REFERENCES @@ -866,53 +884,56 @@ inline move_insert_iterator move_inserter(C& x, typename C::iterator it) // ////////////////////////////////////////////////////////////////////////////// +#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; + //! 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; } - return result; -} -////////////////////////////////////////////////////////////////////////////// -// -// move_backward -// -////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// + // + // 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); + //! 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; } - return result; -} + +#endif //!defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE) ////////////////////////////////////////////////////////////////////////////// // @@ -956,6 +977,7 @@ F uninitialized_move(I f, I l, F r, return std::uninitialized_copy(f, l, r); } */ + ////////////////////////////////////////////////////////////////////////////// // // uninitialized_copy_or_move @@ -1098,4 +1120,13 @@ struct has_trivial_destructor_after_move } //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 + #undef _SCL_SECURE_NO_WARNINGS + #endif +#endif + #endif //#ifndef BOOST_MOVE_MOVE_HPP From da8c25e0afa13bebb75f7a3881649f5c09bf8873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 28 Aug 2011 09:41:10 +0000 Subject: [PATCH 6/8] Code cleanup [SVN r74098] --- proj/vc7ide/Move.sln | 1 + 1 file changed, 1 insertion(+) diff --git a/proj/vc7ide/Move.sln b/proj/vc7ide/Move.sln index 68e086e..894918a 100644 --- a/proj/vc7ide/Move.sln +++ b/proj/vc7ide/Move.sln @@ -132,6 +132,7 @@ Global ..\..\doc\Jamfile.v2 = ..\..\doc\Jamfile.v2 ..\..\..\..\boost\move\move.hpp = ..\..\..\..\boost\move\move.hpp ..\..\doc\move.qbk = ..\..\doc\move.qbk + ..\..\..\..\boost\move\move_helpers.hpp = ..\..\..\..\boost\move\move_helpers.hpp EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection From 9cc7307b030931cec43cf2f37efba58b7fa32838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 29 Aug 2011 11:22:19 +0000 Subject: [PATCH 7/8] Fixes for clang + cleanup [SVN r74125] --- include/boost/move/move.hpp | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/include/boost/move/move.hpp b/include/boost/move/move.hpp index 40c5c2c..86cd032 100644 --- a/include/boost/move/move.hpp +++ b/include/boost/move/move.hpp @@ -45,7 +45,6 @@ #include #include #include - #include #include #include #include @@ -184,31 +183,6 @@ ( ::boost::move_detail::addr_impl_ref( v ), 0 ); } - /* - typedef char one; - struct two {one _[2];}; - - template - struct is_base_of_host - { - operator B*() const; - operator D*(); - }; - - template - struct is_base_of - { - typedef char yes; - class no { char dummy[2]; }; - - template - static yes check(D*, T); - static no check(B*, int); - - static const bool value = sizeof(check(is_base_of_host(), int())) == sizeof(yes); - }; - */ - } //namespace move_detail { } //namespace boost { @@ -217,7 +191,7 @@ //Compiler workaround detection #if !defined(BOOST_NO_RVALUE_REFERENCES) - #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 5) + #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) From 664d8ba073d5437446b150b4bb70d21156ba676b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 30 Aug 2011 12:53:03 +0000 Subject: [PATCH 8/8] Updated documentation and tests to Boost.Container [SVN r74156] --- doc/move.qbk | 7 +++---- example/doc_file_descriptor.cpp | 6 +++--- example/doc_move_inserter.cpp | 4 ++-- example/doc_move_iterator.cpp | 4 ++-- test/back_move_inserter.cpp | 14 +++++++------- test/move_algorithm.cpp | 8 ++++---- test/move_iterator.cpp | 8 ++++---- 7 files changed, 25 insertions(+), 26 deletions(-) diff --git a/doc/move.qbk b/doc/move.qbk index 1558d35..1275a56 100644 --- a/doc/move.qbk +++ b/doc/move.qbk @@ -18,12 +18,11 @@ ] ] -[important To be able to use containers of movable-only values you will need to use containers supporting move sematantics, - like [*Boost.Interprocess] containers] +[important To be able to use containers of movable-only values you will need to use containers +supporting move semantics, like [*Boost.Container] containers] [note Tested compilers: MSVC-7.1, 8.0, 9.0, GCC 4.3-MinGW in C++03 and C++0x modes, Intel 10.1] - [section:what_is_boost_move What is Boost.Move?] Rvalue references are a major C++0x feature, enabling move semantics for C++ values. However, we @@ -285,7 +284,7 @@ movable and copyable types are more efficiently handled if those containers internally use move semantics instead of copy semantics. If the container needs to "change the location" of an element internally (e.g. vector reallocation) it will move the element instead of copying it. -[*Boost.Interprocess] containers are move-aware so you can write the following: +[*Boost.Container] containers are move-aware so you can write the following: [file_descriptor_example] diff --git a/example/doc_file_descriptor.cpp b/example/doc_file_descriptor.cpp index 0691ebb..6d008d3 100644 --- a/example/doc_file_descriptor.cpp +++ b/example/doc_file_descriptor.cpp @@ -56,7 +56,7 @@ class file_descriptor //] //[file_descriptor_example -#include +#include #include //Remember: 'file_descriptor' is NOT copyable, but it @@ -72,7 +72,7 @@ int main() assert(!fd.empty()); //Now move fd into a vector - boost::interprocess::vector v; + boost::container::vector v; v.push_back(boost::move(fd)); //Check ownership has been transferred @@ -81,7 +81,7 @@ int main() //Compilation error if uncommented since file_descriptor is not copyable //and vector copy construction requires value_type's copy constructor: - //boost::interprocess::vector v2(v); + //boost::container::vector v2(v); return 0; } //] diff --git a/example/doc_move_inserter.cpp b/example/doc_move_inserter.cpp index 547cc82..1e0b9dc 100644 --- a/example/doc_move_inserter.cpp +++ b/example/doc_move_inserter.cpp @@ -10,11 +10,11 @@ ////////////////////////////////////////////////////////////////////////////// //[move_inserter_example -#include +#include #include "movable.hpp" #include -using namespace ::boost::interprocess; +using namespace ::boost::container; typedef list list_t; typedef list_t::iterator l_iterator; diff --git a/example/doc_move_iterator.cpp b/example/doc_move_iterator.cpp index d48b93f..0e7cc51 100644 --- a/example/doc_move_iterator.cpp +++ b/example/doc_move_iterator.cpp @@ -10,13 +10,13 @@ ////////////////////////////////////////////////////////////////////////////// //[move_iterator_example -#include +#include #include "movable.hpp" #include int main() { - using namespace ::boost::interprocess; + using namespace ::boost::container; //Create a vector with 10 default constructed objects vector v(10); diff --git a/test/back_move_inserter.cpp b/test/back_move_inserter.cpp index 27d28f4..ca4720b 100644 --- a/test/back_move_inserter.cpp +++ b/test/back_move_inserter.cpp @@ -9,9 +9,9 @@ // ////////////////////////////////////////////////////////////////////////////// #include -#include -#include -#include +#include +#include +#include #include "../example/movable.hpp" template @@ -46,15 +46,15 @@ int move_test() int main() { - namespace bi = ::boost::interprocess; + namespace bc = ::boost::container; - if(move_test< bi::vector >()){ + if(move_test< bc::vector >()){ return 1; } - if(move_test< bi::list >()){ + if(move_test< bc::list >()){ return 1; } - if(move_test< bi::stable_vector >()){ + if(move_test< bc::stable_vector >()){ return 1; } return 0; diff --git a/test/move_algorithm.cpp b/test/move_algorithm.cpp index 86db155..0568f7c 100644 --- a/test/move_algorithm.cpp +++ b/test/move_algorithm.cpp @@ -9,15 +9,15 @@ // ////////////////////////////////////////////////////////////////////////////// #include -#include +#include #include "../example/movable.hpp" int main() { - namespace bi = ::boost::interprocess; + namespace bc = ::boost::container; //Default construct 10 movable objects - bi::vector v(10); - bi::vector v2(10); + bc::vector v(10); + bc::vector v2(10); //Move to v2 boost::move(v.begin(), v.end(), v2.begin()); diff --git a/test/move_iterator.cpp b/test/move_iterator.cpp index 05a524b..10cc2bd 100644 --- a/test/move_iterator.cpp +++ b/test/move_iterator.cpp @@ -10,14 +10,14 @@ ////////////////////////////////////////////////////////////////////////////// #include -#include +#include #include "../example/movable.hpp" int main() { - namespace bi = ::boost::interprocess; + namespace bc = ::boost::container; //Default construct 10 movable objects - bi::vector v(10); + bc::vector v(10); //Test default constructed value if(v[0].moved()){ @@ -25,7 +25,7 @@ int main() } //Move values - bi::vector v2 + bc::vector v2 (boost::make_move_iterator(v.begin()), boost::make_move_iterator(v.end())); //Test values have been moved