*** /usr/include/boost/optional/optional.hpp 2012-11-16 01:54:00.000000000 +0100 --- optional.hpp 2013-02-05 15:02:07.917622463 +0100 *************** *** 11,16 **** --- 11,17 ---- // // Revisions: // 27 Apr 2008 (improved swap) Fernando Cacciola, Niels Dekker, Thorsten Ottosen + // 5 Feb 2013 (move construction/assignment) Diggory Hardy // #ifndef BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP #define BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP *************** struct types_when_isnt_ref *** 155,160 **** --- 156,162 ---- typedef T const* pointer_const_type ; typedef T * pointer_type ; typedef T const& argument_type ; + typedef T && argument_move_type; } ; template struct types_when_is_ref *************** struct types_when_is_ref *** 166,171 **** --- 168,174 ---- typedef raw_type* pointer_const_type ; typedef raw_type* pointer_type ; typedef raw_type& argument_type ; + typedef raw_type&& argument_move_type; } ; struct optional_tag {} ; *************** class optional_base : public optional_ta *** 208,213 **** --- 211,217 ---- typedef BOOST_DEDUCED_TYPENAME types::pointer_type pointer_type ; typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type pointer_const_type ; typedef BOOST_DEDUCED_TYPENAME types::argument_type argument_type ; + typedef BOOST_DEDUCED_TYPENAME types::argument_move_type argument_move_type ; // Creates an optional uninitialized. // No-throw *************** class optional_base : public optional_ta *** 230,235 **** --- 234,248 ---- construct(val); } + // Creates an optional move-constructed from 'val'. + // Can throw if T::T(T const&) does + optional_base ( argument_move_type val ) + : + m_initialized(false) + { + construct(std::move(val)); + } + // Creates an optional initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional. // Can throw if T::T(T const&) does optional_base ( bool cond, argument_type val ) *************** class optional_base : public optional_ta *** 240,245 **** --- 253,268 ---- construct(val); } + // Creates an optional move-construted with 'val' IFF cond is true, otherwise creates an uninitialzed optional. + // Can throw if T::T(T const&) does + optional_base ( bool cond, argument_move_type val ) + : + m_initialized(false) + { + if ( cond ) + construct(std::move(val)); + } + // Creates a deep copy of another optional // Can throw if T::T(T const&) does optional_base ( optional_base const& rhs ) *************** class optional_base : public optional_ta *** 250,255 **** --- 273,291 ---- construct(rhs.get_impl()); } + // Move-constructs from another optional + // Can throw if T::T(T &&) does + #if 0 + //TODO: non-trivial to implement and possibly not needed + optional_base ( optional_base && rhs ) + : + m_initialized(false) + { + if ( rhs.is_initialized() ) + construct(rhs.release_impl()); // something like "release" needed + } + #endif + // This is used for both converting and in-place constructions. // Derived classes use the 'tag' to select the appropriate *************** class optional_base : public optional_ta *** 308,313 **** --- 344,357 ---- else construct(val); } + // Assigns from a T (move-copies the rhs value) + void assign ( argument_move_type val ) + { + if (is_initialized()) + assign_value(std::move(val), is_reference_predicate() ); + else construct(std::move(val)); + } + // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED // No-throw (assuming T::~T() doesn't) void assign ( none_t ) { destroy(); } *************** class optional_base : public optional_ta *** 331,336 **** --- 375,383 ---- // Replaces the current value -if any- with 'val' void reset ( argument_type val ) { assign(val); } + // Replaces the current value -if any- with 'val' + void reset ( argument_move_type val ) { assign(std::move(val)); } + // Returns a pointer to the value if this is initialized, otherwise, // returns NULL. // No-throw *************** class optional_base : public optional_ta *** 347,352 **** --- 394,405 ---- m_initialized = true ; } + void construct ( argument_move_type val ) + { + new (m_storage.address()) internal_type(std::move(val)) ; + m_initialized = true ; + } + #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT // Constructs in-place using the given factory template *************** class optional_base : public optional_ta *** 430,437 **** } #endif ! void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; } ! void assign_value ( argument_type val, is_reference_tag ) { construct(val); } void destroy() { --- 483,496 ---- } #endif ! void assign_value ( argument_type val, is_not_reference_tag ) { ! get_impl() = val; } ! void assign_value ( argument_move_type val, is_not_reference_tag ) { ! get_impl() = std::move(val); } ! void assign_value ( argument_type val, is_reference_tag ) { ! construct(val); } ! void assign_value ( argument_move_type val, is_reference_tag ) { ! construct(std::move(val)); } void destroy() { *************** class optional : public optional_detail: *** 512,517 **** --- 571,577 ---- typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ; typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ; typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ; + typedef BOOST_DEDUCED_TYPENAME base::argument_move_type argument_move_type ; // Creates an optional uninitialized. // No-throw *************** class optional : public optional_detail: *** 525,534 **** --- 585,602 ---- // Can throw if T::T(T const&) does optional ( argument_type val ) : base(val) {} + // Creates an optional move-constructed from 'val'. + // Can throw if T::T(T const&) does + optional ( argument_move_type val ) : base(std::move(val)) {} + // Creates an optional initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional. // Can throw if T::T(T const&) does optional ( bool cond, argument_type val ) : base(cond,val) {} + // Creates an optional move-constructed from 'val' IFF cond is true, otherwise creates an uninitialized optional. + // Can throw if T::T(T const&) does + optional ( bool cond, argument_move_type val ) : base(cond,std::move(val)) {} + #ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR // NOTE: MSVC needs templated versions first *************** class optional : public optional_detail: *** 563,568 **** --- 631,643 ---- // Can throw if T::T(T const&) does optional ( optional const& rhs ) : base( static_cast(rhs) ) {} + // Moves from another optional, leaving that uninitialised + // Can throw if T::T(T const&) does + optional ( optional && rhs ) : base() { + *this = std::move( rhs.get() ); + rhs = boost::none; + } + // No-throw (assuming T::~T() doesn't) ~optional() {} *************** class optional : public optional_detail: *** 606,611 **** --- 681,694 ---- this->assign( val ) ; return *this ; } + // Assigns from a T (move-copies the rhs value) + // Basic Guarantee: If T::( T && ) throws, this is left UNINITIALIZED + optional& operator= ( argument_move_type val ) + { + this->assign( std::move(val) ) ; + return *this ; + } + // Assigns from a "none" // Which destroys the current value, if any, leaving this UNINITIALIZED *************** struct swap_selector *** 960,971 **** if ( !hasX && hasY ) { ! x = y.get(); y = boost::none ; } else if ( hasX && !hasY ) { ! y = x.get(); x = boost::none ; } else if ( hasX && hasY ) --- 1043,1054 ---- if ( !hasX && hasY ) { ! x = std::move(y.get()); y = boost::none ; } else if ( hasX && !hasY ) { ! y = std::move(x.get()); x = boost::none ; } else if ( hasX && hasY )