forked from boostorg/optional
Compiler compatibility fixes; Reference assignment changed (if the lhs is initialized, the assignment goes to the referenced object, thus the reference is not rebound)
[SVN r20546]
This commit is contained in:
@ -43,7 +43,7 @@
|
|||||||
// However, optional's ctor is _explicit_ and the assignemt shouldn't compile.
|
// However, optional's ctor is _explicit_ and the assignemt shouldn't compile.
|
||||||
// Therefore, for VC6.0 templated assignment is disabled.
|
// Therefore, for VC6.0 templated assignment is disabled.
|
||||||
//
|
//
|
||||||
#define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
#define BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
|
#if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
|
||||||
@ -53,9 +53,25 @@
|
|||||||
// given to the non-templated version, making the class non-implicitely-copyable.
|
// given to the non-templated version, making the class non-implicitely-copyable.
|
||||||
//
|
//
|
||||||
#define BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
|
#define BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||||
|
// AFAICT only VC7.1 correctly resolves the overload set
|
||||||
|
// that includes the in-place factory taking functions,
|
||||||
|
// so for the other VC versions, in-place factory support
|
||||||
|
// is disabled
|
||||||
#define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
#define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_WORKAROUND(__BORLANDC__, <= 0x564)
|
||||||
|
// VC7.0 has the following bug:
|
||||||
|
// When both a non-template and a template copy-ctor exist
|
||||||
|
// and the templated version is made 'explicit', the explicit is also
|
||||||
|
// given to the non-templated version, making the class non-implicitely-copyable.
|
||||||
|
//
|
||||||
|
#define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
|
|
||||||
class InPlaceFactoryBase ;
|
class InPlaceFactoryBase ;
|
||||||
@ -105,8 +121,10 @@ struct types_when_is_ref
|
|||||||
typedef raw_type& argument_type ;
|
typedef raw_type& argument_type ;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
struct optional_tag {} ;
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
class optional_base
|
class optional_base : public optional_tag
|
||||||
{
|
{
|
||||||
private :
|
private :
|
||||||
|
|
||||||
@ -138,7 +156,7 @@ class optional_base
|
|||||||
|
|
||||||
// Creates an optional<T> uninitialized.
|
// Creates an optional<T> uninitialized.
|
||||||
// No-throw
|
// No-throw
|
||||||
optional_base ()
|
optional_base()
|
||||||
:
|
:
|
||||||
m_initialized(false) {}
|
m_initialized(false) {}
|
||||||
|
|
||||||
@ -183,68 +201,30 @@ class optional_base
|
|||||||
|
|
||||||
// Assigns from another optional<T> (deep-copies the rhs value)
|
// Assigns from another optional<T> (deep-copies the rhs value)
|
||||||
// Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
|
// Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
|
||||||
optional_base& operator= ( optional_base const& rhs )
|
void assign ( optional_base const& rhs ) { assign_impl(rhs,is_reference_predicate()); }
|
||||||
{
|
|
||||||
destroy(); // no-throw
|
|
||||||
|
|
||||||
if ( rhs.is_initialized() )
|
|
||||||
{
|
|
||||||
// An exception can be thrown here.
|
|
||||||
// If it happens, THIS will be left uninitialized.
|
|
||||||
construct(rhs.get_impl());
|
|
||||||
}
|
|
||||||
return *this ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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_base& operator= ( argument_type val )
|
void assign ( argument_type val ) { assign_impl(val,is_reference_predicate()); }
|
||||||
{
|
|
||||||
destroy(); // no-throw
|
|
||||||
|
|
||||||
// An exception can be thrown here.
|
|
||||||
// If it happens, THIS will be left uninitialized.
|
|
||||||
construct(val);
|
|
||||||
|
|
||||||
return *this ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
||||||
optional_base& operator= ( detail::none_t const& )
|
void assign ( detail::none_t const& ) { destroy(); }
|
||||||
{
|
|
||||||
reset();
|
|
||||||
return *this ;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||||
template<class Expr>
|
template<class Expr>
|
||||||
void assign_expr ( Expr const& expr, Expr const* tag )
|
void assign_expr ( Expr const& expr, Expr const* tag ) { assign_expr_impl(expr,tag,is_reference_predicate()) ; }
|
||||||
{
|
|
||||||
destroy(); // no-throw
|
|
||||||
|
|
||||||
// An exception can be thrown here.
|
|
||||||
// If it happens, THIS will be left uninitialized.
|
|
||||||
construct(expr,tag);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public :
|
public :
|
||||||
|
|
||||||
// Destroys the current value, if any, leaving this UNINITIALIZED
|
// Destroys the current value, if any, leaving this UNINITIALIZED
|
||||||
// No-throw (assuming T::~T() doesn't)
|
// No-throw (assuming T::~T() doesn't)
|
||||||
void reset()
|
void reset() { destroy(); }
|
||||||
{
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replaces the current value -if any- with 'val'
|
// Replaces the current value -if any- with 'val'
|
||||||
// Basic Guarantee: If T::T( T const& ) throws this is left UNINITIALIZED.
|
// Basic Guarantee: If T::T( T const& ) throws this is left UNINITIALIZED.
|
||||||
void reset ( argument_type val )
|
void reset ( argument_type val ) { assign_impl(val,is_reference_predicate()); }
|
||||||
{
|
|
||||||
destroy();
|
|
||||||
construct(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a pointer to the value if this is initialized, otherwise,
|
// Returns a pointer to the value if this is initialized, otherwise,
|
||||||
// returns NULL.
|
// returns NULL.
|
||||||
@ -293,6 +273,117 @@ class optional_base
|
|||||||
m_initialized = true ;
|
m_initialized = true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Expr>
|
||||||
|
void assign_expr_to_ref ( Expr const& expr, void const* )
|
||||||
|
{
|
||||||
|
get_impl() = expr ;
|
||||||
|
m_initialized = true ;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
|
||||||
|
// BCB5.64 (and probably lower versions) workaround.
|
||||||
|
// The in-place factories are supported by means of catch-all constructors
|
||||||
|
// and assignment operators (the functions are parameterized in terms of
|
||||||
|
// an arbitrary 'Expr' type)
|
||||||
|
// This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U>
|
||||||
|
// to the 'Expr'-taking functions even though explicit overloads are present for them.
|
||||||
|
// Thus, the following overload is needed to properly handle the case when the 'lhs'
|
||||||
|
// is another optional.
|
||||||
|
//
|
||||||
|
// For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error
|
||||||
|
// instead of choosing the wrong overload
|
||||||
|
//
|
||||||
|
// Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
|
||||||
|
template<class Expr>
|
||||||
|
void construct ( Expr const& expr, optional_tag const* )
|
||||||
|
{
|
||||||
|
if ( expr.is_initialized() )
|
||||||
|
{
|
||||||
|
// An exception can be thrown here.
|
||||||
|
// It it happens, THIS will be left uninitialized.
|
||||||
|
new (m_storage.address()) internal_type(expr.get()) ;
|
||||||
|
m_initialized = true ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<class Expr>
|
||||||
|
void assign_expr_to_ref ( Expr const& expr, optional_tag const* )
|
||||||
|
{
|
||||||
|
if ( expr.is_initialized() )
|
||||||
|
{
|
||||||
|
// An exception can be thrown here.
|
||||||
|
// It it happens, THIS will be left uninitialized.
|
||||||
|
get_impl() = expr.get() ;
|
||||||
|
m_initialized = true ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void assign_impl ( optional_base const& rhs, is_not_reference_tag tag )
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
if ( rhs.is_initialized() )
|
||||||
|
construct(rhs.get_impl());
|
||||||
|
}
|
||||||
|
|
||||||
|
void assign_impl ( optional_base const& rhs, is_reference_tag )
|
||||||
|
{
|
||||||
|
if ( is_initialized() )
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
if ( rhs.is_initialized() )
|
||||||
|
assign_to_referenced(rhs.get_impl());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( rhs.is_initialized() )
|
||||||
|
construct(rhs.get_impl());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void assign_impl ( argument_type val, is_not_reference_tag )
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
construct(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void assign_impl ( argument_type val, is_reference_tag )
|
||||||
|
{
|
||||||
|
if ( is_initialized() )
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
assign_to_referenced(val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
construct(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||||
|
template<class Expr>
|
||||||
|
void assign_expr_impl ( Expr const& expr, Expr const* expr_tag, is_not_reference_tag )
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
construct(expr,expr_tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Expr>
|
||||||
|
void assign_expr_impl ( Expr const& expr, Expr const* expr_tag, is_reference_tag )
|
||||||
|
{
|
||||||
|
if ( is_initialized() )
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
assign_expr_to_ref(expr,expr_tag);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
construct(expr,expr_tag);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void assign_to_referenced ( argument_type val )
|
||||||
|
{
|
||||||
|
get_impl() = val ;
|
||||||
|
m_initialized = true ;
|
||||||
|
}
|
||||||
|
|
||||||
void destroy()
|
void destroy()
|
||||||
{
|
{
|
||||||
if ( m_initialized )
|
if ( m_initialized )
|
||||||
@ -319,7 +410,6 @@ class optional_base
|
|||||||
reference_const_type dereference( internal_type const* p, is_reference_tag ) const { return p->get() ; }
|
reference_const_type dereference( internal_type const* p, is_reference_tag ) const { return p->get() ; }
|
||||||
reference_type dereference( internal_type* p, is_reference_tag ) { return p->get() ; }
|
reference_type dereference( internal_type* p, is_reference_tag ) { return p->get() ; }
|
||||||
|
|
||||||
// BCC564 complains about get_object()->~internal_type(), so the following dispatch is neccesary.
|
|
||||||
void destroy_impl ( is_not_reference_tag ) { get_impl().~T() ; m_initialized = false ; }
|
void destroy_impl ( is_not_reference_tag ) { get_impl().~T() ; m_initialized = false ; }
|
||||||
void destroy_impl ( is_reference_tag ) { m_initialized = false ; }
|
void destroy_impl ( is_reference_tag ) { m_initialized = false ; }
|
||||||
|
|
||||||
@ -378,7 +468,7 @@ class optional : public optional_detail::optional_base<T>
|
|||||||
base()
|
base()
|
||||||
{
|
{
|
||||||
if ( rhs.is_initialized() )
|
if ( rhs.is_initialized() )
|
||||||
construct(rhs.get());
|
this->construct(rhs.get());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -388,6 +478,8 @@ class optional : public optional_detail::optional_base<T>
|
|||||||
// (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
|
// (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
|
||||||
// (c) Any expression implicitely convertible to the single type
|
// (c) Any expression implicitely convertible to the single type
|
||||||
// of a one-argument T's constructor.
|
// of a one-argument T's constructor.
|
||||||
|
// (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
|
||||||
|
// even though explicit overloads are present for these.
|
||||||
// Depending on the above some T ctor is called.
|
// Depending on the above some T ctor is called.
|
||||||
// Can throw is the resolved T ctor throws.
|
// Can throw is the resolved T ctor throws.
|
||||||
template<class Expr>
|
template<class Expr>
|
||||||
@ -401,28 +493,42 @@ class optional : public optional_detail::optional_base<T>
|
|||||||
// No-throw (assuming T::~T() doesn't)
|
// No-throw (assuming T::~T() doesn't)
|
||||||
~optional() {}
|
~optional() {}
|
||||||
|
|
||||||
|
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||||
|
// Assigns from an expression. See corresponding constructor.
|
||||||
|
// Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
|
||||||
|
template<class Expr>
|
||||||
|
optional& operator= ( Expr expr )
|
||||||
|
{
|
||||||
|
this->assign_expr(expr,&expr);
|
||||||
|
return *this ;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
|
||||||
// Assigns from another convertible optional<U> (converts && deep-copies the rhs value)
|
// Assigns from another convertible optional<U> (converts && deep-copies the rhs value)
|
||||||
// Requires a valid conversion from U to T.
|
// Requires a valid conversion from U to T.
|
||||||
// Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
|
// Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
|
||||||
template<class U>
|
template<class U>
|
||||||
optional& operator= ( optional<U> const& rhs )
|
optional& operator= ( optional<U> const& rhs )
|
||||||
{
|
{
|
||||||
destroy(); // no-throw
|
this->destroy(); // no-throw
|
||||||
|
|
||||||
if ( rhs.is_initialized() )
|
if ( rhs.is_initialized() )
|
||||||
{
|
{
|
||||||
// An exception can be thrown here.
|
// An exception can be thrown here.
|
||||||
// It it happens, THIS will be left uninitialized.
|
// It it happens, THIS will be left uninitialized.
|
||||||
construct(rhs.get());
|
this->assign_val(rhs.get());
|
||||||
}
|
}
|
||||||
return *this ;
|
return *this ;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Assigns from another optional<T> (deep-copies the rhs value)
|
// Assigns from another optional<T> (deep-copies the rhs value)
|
||||||
// Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
|
// Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
|
||||||
|
// (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
|
||||||
optional& operator= ( optional const& rhs )
|
optional& operator= ( optional const& rhs )
|
||||||
{
|
{
|
||||||
this->base::operator= ( rhs ) ;
|
this->assign( rhs ) ;
|
||||||
return *this ;
|
return *this ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,7 +536,7 @@ class optional : public optional_detail::optional_base<T>
|
|||||||
// 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 )
|
||||||
{
|
{
|
||||||
this->base::operator= ( val ) ;
|
this->assign( val ) ;
|
||||||
return *this ;
|
return *this ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,21 +545,10 @@ class optional : public optional_detail::optional_base<T>
|
|||||||
// No-throw (assuming T::~T() doesn't)
|
// No-throw (assuming T::~T() doesn't)
|
||||||
optional& operator= ( detail::none_t const& none_ )
|
optional& operator= ( detail::none_t const& none_ )
|
||||||
{
|
{
|
||||||
this->base::operator= ( none_ ) ;
|
this->assign( none_ ) ;
|
||||||
return *this ;
|
return *this ;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
|
||||||
// Assigns from an expression. See corresponding constructor.
|
|
||||||
// Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
|
|
||||||
template<class Expr>
|
|
||||||
optional& operator= ( Expr expr )
|
|
||||||
{
|
|
||||||
this->base::assign_expr(expr,&expr);
|
|
||||||
return *this ;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Returns a reference to the value if this is initialized, otherwise,
|
// Returns a reference to the value if this is initialized, otherwise,
|
||||||
// the behaviour is UNDEFINED
|
// the behaviour is UNDEFINED
|
||||||
// No-throw
|
// No-throw
|
||||||
|
Reference in New Issue
Block a user