Added 'raw' move semantics; no unit-tests

This commit is contained in:
Andrzej Krzemienski
2014-04-14 23:44:34 +02:00
parent b4738ac07e
commit 587ef8e988

View File

@ -131,6 +131,9 @@ struct types_when_isnt_ref
{ {
typedef T const& reference_const_type ; typedef T const& reference_const_type ;
typedef T & reference_type ; typedef T & reference_type ;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typedef T && rval_reference_type ;
#endif
typedef T const* pointer_const_type ; typedef T const* pointer_const_type ;
typedef T * pointer_type ; typedef T * pointer_type ;
typedef T const& argument_type ; typedef T const& argument_type ;
@ -140,11 +143,14 @@ struct types_when_is_ref
{ {
typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type raw_type ; typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type raw_type ;
typedef raw_type& reference_const_type ; typedef raw_type& reference_const_type ;
typedef raw_type& reference_type ; typedef raw_type& reference_type ;
typedef raw_type* pointer_const_type ; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typedef raw_type* pointer_type ; typedef raw_type&& rval_reference_type ;
typedef raw_type& argument_type ; #endif
typedef raw_type* pointer_const_type ;
typedef raw_type* pointer_type ;
typedef raw_type& argument_type ;
} ; } ;
struct optional_tag {} ; struct optional_tag {} ;
@ -184,6 +190,9 @@ class optional_base : public optional_tag
typedef BOOST_DEDUCED_TYPENAME types::reference_type reference_type ; typedef BOOST_DEDUCED_TYPENAME types::reference_type reference_type ;
typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ; typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typedef BOOST_DEDUCED_TYPENAME types::rval_reference_type rval_reference_type ;
#endif
typedef BOOST_DEDUCED_TYPENAME types::pointer_type pointer_type ; 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::pointer_const_type pointer_const_type ;
typedef BOOST_DEDUCED_TYPENAME types::argument_type argument_type ; typedef BOOST_DEDUCED_TYPENAME types::argument_type argument_type ;
@ -209,6 +218,17 @@ class optional_base : public optional_tag
construct(val); construct(val);
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// move-construct an optional<T> initialized from an rvalue-ref to 'val'.
// Can throw if T::T(T&&) does
optional_base ( rval_reference_type val )
:
m_initialized(false)
{
construct( static_cast<T&&>(val) );
}
#endif
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>. // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>.
// Can throw if T::T(T const&) does // Can throw if T::T(T const&) does
optional_base ( bool cond, argument_type val ) optional_base ( bool cond, argument_type val )
@ -229,6 +249,17 @@ class optional_base : public optional_tag
construct(rhs.get_impl()); construct(rhs.get_impl());
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Creates a deep move of another optional<T>
// Can throw if T::T(T&&) does
optional_base ( optional_base&& rhs )
:
m_initialized(false)
{
if ( rhs.is_initialized() )
construct( static_cast<T&&>(rhs.get_impl()) );
}
#endif
// This is used for both converting and in-place constructions. // This is used for both converting and in-place constructions.
// Derived classes use the 'tag' to select the appropriate // Derived classes use the 'tag' to select the appropriate
@ -279,6 +310,26 @@ class optional_base : public optional_tag
} }
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// move-assigns from another _convertible_ optional<U> (deep-moves from the rhs value)
template<class U>
void assign ( optional<U>&& rhs )
{
typedef BOOST_DEDUCED_TYPENAME optional<U>::rval_reference_type ref_type;
if (is_initialized())
{
if ( rhs.is_initialized() )
assign_value(static_cast<ref_type>(rhs.get()), is_reference_predicate() );
else destroy();
}
else
{
if ( rhs.is_initialized() )
construct(static_cast<ref_type>(rhs.get()));
}
}
#endif
// Assigns from a T (deep-copies the rhs value) // Assigns from a T (deep-copies the rhs value)
void assign ( argument_type val ) void assign ( argument_type val )
{ {
@ -286,6 +337,16 @@ class optional_base : public optional_tag
assign_value(val, is_reference_predicate() ); assign_value(val, is_reference_predicate() );
else construct(val); else construct(val);
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Assigns from a T (deep-moves the rhs value)
void assign ( rval_reference_type val )
{
if (is_initialized())
assign_value( static_cast<rval_reference_type>(val), is_reference_predicate() );
else construct( static_cast<rval_reference_type>(val) );
}
#endif
// Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't) // No-throw (assuming T::~T() doesn't)
@ -325,6 +386,14 @@ class optional_base : public optional_tag
new (m_storage.address()) internal_type(val) ; new (m_storage.address()) internal_type(val) ;
m_initialized = true ; m_initialized = true ;
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
void construct ( rval_reference_type val )
{
new (m_storage.address()) internal_type( static_cast<rval_reference_type>(val) ) ;
m_initialized = true ;
}
#endif
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
// Constructs in-place using the given factory // Constructs in-place using the given factory
@ -411,6 +480,10 @@ class optional_base : public optional_tag
void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; } 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 assign_value ( argument_type val, is_reference_tag ) { construct(val); }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
void assign_value ( rval_reference_type val, is_not_reference_tag ) { get_impl() = static_cast<rval_reference_type>(val); }
void assign_value ( rval_reference_type val, is_reference_tag ) { construct( static_cast<rval_reference_type>(val) ); }
#endif
void destroy() void destroy()
{ {
@ -488,22 +561,34 @@ class optional : public optional_detail::optional_base<T>
typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ; typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ;
typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ; typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ;
typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ; typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type rval_reference_type ;
#endif
typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ; 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::pointer_const_type pointer_const_type ;
typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ; typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
// Creates an optional<T> uninitialized. // Creates an optional<T> uninitialized.
// No-throw // No-throw
optional() : base() {} optional() BOOST_NOEXCEPT : base() {}
// Creates an optional<T> uninitialized. // Creates an optional<T> uninitialized.
// No-throw // No-throw
optional( none_t none_ ) : base(none_) {} optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {}
// Creates an optional<T> initialized with 'val'. // Creates an optional<T> initialized with 'val'.
// Can throw if T::T(T const&) does // Can throw if T::T(T const&) does
optional ( argument_type val ) : base(val) {} optional ( argument_type val ) : base(val) {}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Creates an optional<T> initialized with 'move(val)'.
// Can throw if T::T(T &&) does
optional ( rval_reference_type val ) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(static_cast<T&&>(val))))
:
base( static_cast<T&&>(val) )
{}
#endif
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional. // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
// Can throw if T::T(T const&) does // Can throw if T::T(T const&) does
optional ( bool cond, argument_type val ) : base(cond,val) {} optional ( bool cond, argument_type val ) : base(cond,val) {}
@ -521,6 +606,20 @@ class optional : public optional_detail::optional_base<T>
if ( rhs.is_initialized() ) if ( rhs.is_initialized() )
this->construct(rhs.get()); this->construct(rhs.get());
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Creates a deep move of another convertible optional<U>
// Requires a valid conversion from U to T.
// Can throw if T::T(U&&) does
template<class U>
explicit optional ( optional<U> && rhs )
:
base()
{
if ( rhs.is_initialized() )
this->construct( static_cast<BOOST_DEDUCED_TYPENAME optional<U>::rval_reference_type>(rhs.get()) );
}
#endif
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
// Creates an optional<T> with an expression which can be either // Creates an optional<T> with an expression which can be either
@ -573,6 +672,16 @@ class optional : public optional_detail::optional_base<T>
return *this ; return *this ;
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Assigns from another optional<T> (deep-moves the rhs value)
optional& operator= ( optional && rhs )
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(static_cast<optional &&>(*rhs))) && BOOST_NOEXCEPT_EXPR(*rhs = static_cast<optional &&>(*rhs)))
{
this->assign( static_cast<optional &&>(rhs) ) ;
return *this ;
}
#endif
// Assigns from a T (deep-copies the rhs value) // Assigns from a T (deep-copies the rhs value)
// Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
optional& operator= ( argument_type val ) optional& operator= ( argument_type val )
@ -581,6 +690,15 @@ class optional : public optional_detail::optional_base<T>
return *this ; return *this ;
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Assigns from a T (deep-moves the rhs value)
optional& operator= ( rval_reference_type val )
{
this->assign( static_cast<rval_reference_type>(val) ) ;
return *this ;
}
#endif
// Assigns from a "none" // Assigns from a "none"
// Which destroys the current value, if any, leaving this UNINITIALIZED // Which destroys the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't) // No-throw (assuming T::~T() doesn't)
@ -591,10 +709,10 @@ class optional : public optional_detail::optional_base<T>
} }
void swap( optional & arg ) void swap( optional & arg )
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(static_cast<optional &&>(*arg))) && BOOST_NOEXCEPT_EXPR(*arg = static_cast<optional &&>(*arg)))
{ {
// allow for Koenig lookup // allow for Koenig lookup
using boost::swap; boost::swap(*this, arg);
swap(*this, arg);
} }
@ -961,6 +1079,7 @@ template<class T>
struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor<T> {} ; struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor<T> {} ;
template<class T> inline void swap ( optional<T>& x, optional<T>& y ) template<class T> inline void swap ( optional<T>& x, optional<T>& y )
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(static_cast<optional &&>(*x))) && BOOST_NOEXCEPT_EXPR(*y = static_cast<optional &&>(*x)))
{ {
optional_detail::swap_selector<optional_swap_should_use_default_constructor<T>::value>::optional_swap(x, y); optional_detail::swap_selector<optional_swap_should_use_default_constructor<T>::value>::optional_swap(x, y);
} }