|
|
|
@ -26,14 +26,9 @@
|
|
|
|
|
#include <boost/type_traits/type_with_alignment.hpp>
|
|
|
|
|
#include <boost/type_traits/remove_reference.hpp>
|
|
|
|
|
#include <boost/type_traits/is_reference.hpp>
|
|
|
|
|
#include <boost/type_traits/has_trivial_destructor.hpp>
|
|
|
|
|
#include <boost/type_traits/has_trivial_assign.hpp>
|
|
|
|
|
#include <boost/type_traits/has_trivial_copy.hpp>
|
|
|
|
|
#include <boost/mpl/if.hpp>
|
|
|
|
|
#include <boost/mpl/bool.hpp>
|
|
|
|
|
#include <boost/mpl/not.hpp>
|
|
|
|
|
#include <boost/mpl/and.hpp>
|
|
|
|
|
#include <boost/mpl/or.hpp>
|
|
|
|
|
#include <boost/detail/reference_content.hpp>
|
|
|
|
|
#include <boost/none.hpp>
|
|
|
|
|
#include <boost/utility/swap.hpp>
|
|
|
|
@ -173,19 +168,6 @@ struct types_when_is_ref
|
|
|
|
|
typedef raw_type& argument_type ;
|
|
|
|
|
} ;
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
|
struct optional_dtor_optimized : has_trivial_destructor<T> {};
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
|
struct optional_copy_optimized : mpl::or_<
|
|
|
|
|
is_reference<T>, // refs aren't copyable at all, but optional<T&> should be copy_optimized
|
|
|
|
|
mpl::and_<
|
|
|
|
|
has_trivial_copy<T>,
|
|
|
|
|
has_trivial_assign<T>,
|
|
|
|
|
mpl::bool_< (sizeof(T) <= 128) > // TODO make 128 configurable
|
|
|
|
|
>
|
|
|
|
|
> {};
|
|
|
|
|
|
|
|
|
|
struct optional_tag {} ;
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
@ -217,8 +199,6 @@ class optional_base : public optional_tag
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME mpl::if_<is_reference_predicate,types_when_ref,types_when_not_ref>::type types ;
|
|
|
|
|
typedef optional_dtor_optimized<T> dtor_optimized;
|
|
|
|
|
typedef optional_copy_optimized<T> copy_optimized;
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
typedef bool (this_type::*unspecified_bool_type)() const;
|
|
|
|
@ -262,7 +242,9 @@ class optional_base : public optional_tag
|
|
|
|
|
|
|
|
|
|
// Creates a deep copy of another optional<T>
|
|
|
|
|
// Can throw if T::T(T const&) does
|
|
|
|
|
void optional_base_copy_ctor_impl ( optional_base const& rhs )
|
|
|
|
|
optional_base ( optional_base const& rhs )
|
|
|
|
|
:
|
|
|
|
|
m_initialized(false)
|
|
|
|
|
{
|
|
|
|
|
if ( rhs.is_initialized() )
|
|
|
|
|
construct(rhs.get_impl());
|
|
|
|
@ -283,7 +265,7 @@ class optional_base : public optional_tag
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// No-throw (assuming T::~T() doesn't)
|
|
|
|
|
//~optional_base() { destroy() ; }
|
|
|
|
|
~optional_base() { destroy() ; }
|
|
|
|
|
|
|
|
|
|
// Assigns from another optional<T> (deep-copies the rhs value)
|
|
|
|
|
void assign ( optional_base const& rhs )
|
|
|
|
@ -453,19 +435,9 @@ class optional_base : public optional_tag
|
|
|
|
|
|
|
|
|
|
void destroy()
|
|
|
|
|
{
|
|
|
|
|
if( dtor_optimized::value )
|
|
|
|
|
m_initialized = false ;
|
|
|
|
|
else if ( m_initialized ){
|
|
|
|
|
destroy_impl(is_reference_predicate()) ;
|
|
|
|
|
m_initialized = false ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void destructor_impl() // doesn't reset m_initialized
|
|
|
|
|
{
|
|
|
|
|
if(m_initialized)
|
|
|
|
|
if ( m_initialized )
|
|
|
|
|
destroy_impl(is_reference_predicate()) ;
|
|
|
|
|
}
|
|
|
|
|
template<typename Optional,bool dtor_optimized> friend class optional_dtor_mixin;
|
|
|
|
|
|
|
|
|
|
unspecified_bool_type safe_bool() const { return m_initialized ? &this_type::is_initialized : 0 ; }
|
|
|
|
|
|
|
|
|
@ -502,12 +474,12 @@ class optional_base : public optional_tag
|
|
|
|
|
reference_type dereference( internal_type* p, is_reference_tag ) { return p->get() ; }
|
|
|
|
|
|
|
|
|
|
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
|
|
|
|
|
void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; }
|
|
|
|
|
void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; }
|
|
|
|
|
#else
|
|
|
|
|
void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->T::~T() ; }
|
|
|
|
|
void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->T::~T() ; m_initialized = false ; }
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void destroy_impl ( is_reference_tag ) { }
|
|
|
|
|
void destroy_impl ( is_reference_tag ) { m_initialized = false ; }
|
|
|
|
|
|
|
|
|
|
// If T is of reference type, trying to get a pointer to the held value must result in a compile-time error.
|
|
|
|
|
// Decent compilers should disallow conversions from reference_content<T>* to T*, but just in case,
|
|
|
|
@ -521,75 +493,12 @@ class optional_base : public optional_tag
|
|
|
|
|
storage_type m_storage ;
|
|
|
|
|
} ;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class T,bool copy_optimized>
|
|
|
|
|
struct optional_copier : optional_base<T>
|
|
|
|
|
{
|
|
|
|
|
// does copy and assignment optimization
|
|
|
|
|
typedef optional_detail::optional_base<T> base ;
|
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
|
|
|
|
|
|
|
|
|
|
optional_copier () {}
|
|
|
|
|
|
|
|
|
|
optional_copier ( optional_copier const& rhs ) : base()
|
|
|
|
|
{
|
|
|
|
|
optional_base_copy_ctor_impl(rhs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
optional_copier& operator= ( optional_copier const& rhs )
|
|
|
|
|
{
|
|
|
|
|
this->assign( static_cast<base const&>(rhs) ) ;
|
|
|
|
|
return *this ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class Expr>
|
|
|
|
|
explicit optional_copier ( Expr expr ) : base(expr) {}
|
|
|
|
|
|
|
|
|
|
template<class P1,class P2>
|
|
|
|
|
explicit optional_copier ( P1 p1 ,P2 p2 ) : base(p1,p2) {}
|
|
|
|
|
|
|
|
|
|
optional_copier ( bool cond, argument_type val ) : base(cond,val) {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
struct optional_copier<T, true> : optional_base<T>
|
|
|
|
|
{
|
|
|
|
|
// does copy and assignment optimization
|
|
|
|
|
typedef optional_detail::optional_base<T> base ;
|
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
|
|
|
|
|
|
|
|
|
|
optional_copier () {}
|
|
|
|
|
|
|
|
|
|
//optional_copier ( optional_copier const& rhs ) // default impl does memcpy
|
|
|
|
|
|
|
|
|
|
//optional_copier& operator= ( optional_copier const& rhs ) // default impl does memcpy
|
|
|
|
|
|
|
|
|
|
template<class Expr>
|
|
|
|
|
explicit optional_copier ( Expr expr ) : base(expr) {}
|
|
|
|
|
|
|
|
|
|
template<class P1,class P2>
|
|
|
|
|
explicit optional_copier ( P1 p1 ,P2 p2 ) : base(p1,p2) {}
|
|
|
|
|
|
|
|
|
|
optional_copier ( bool cond, argument_type val ) : base(cond,val) {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<typename Optional,bool dtor_optimized>
|
|
|
|
|
struct optional_dtor_mixin{
|
|
|
|
|
~optional_dtor_mixin(){ static_cast<Optional*>(this)->destructor_impl() ; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<typename Optional>
|
|
|
|
|
struct optional_dtor_mixin<Optional, true > { };
|
|
|
|
|
|
|
|
|
|
} // namespace optional_detail
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
class optional :
|
|
|
|
|
public optional_detail::optional_copier<T, optional_detail::optional_base<T>::copy_optimized::value >,
|
|
|
|
|
public optional_detail::optional_dtor_mixin<optional<T>, optional_detail::optional_base<T>::dtor_optimized::value >
|
|
|
|
|
class optional : public optional_detail::optional_base<T>
|
|
|
|
|
{
|
|
|
|
|
typedef optional_detail::optional_copier<T, optional_detail::optional_base<T>::copy_optimized::value > base ;
|
|
|
|
|
typedef optional_detail::optional_base<T> base ;
|
|
|
|
|
|
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME base::unspecified_bool_type unspecified_bool_type ;
|
|
|
|
|
|
|
|
|
@ -652,10 +561,10 @@ class optional :
|
|
|
|
|
|
|
|
|
|
// Creates a deep copy of another optional<T>
|
|
|
|
|
// Can throw if T::T(T const&) does
|
|
|
|
|
//optional ( optional const& rhs ) // default impl (see optional_copier)
|
|
|
|
|
optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
|
|
|
|
|
|
|
|
|
|
// No-throw (assuming T::~T() doesn't)
|
|
|
|
|
//~optional() {}
|
|
|
|
|
// No-throw (assuming T::~T() doesn't)
|
|
|
|
|
~optional() {}
|
|
|
|
|
|
|
|
|
|
#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
|
|
|
|
|
// Assigns from an expression. See corresponding constructor.
|
|
|
|
@ -684,7 +593,11 @@ class optional :
|
|
|
|
|
// Assigns from another optional<T> (deep-copies the rhs value)
|
|
|
|
|
// 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 ) // default impl (see optional_copier)
|
|
|
|
|
optional& operator= ( optional const& rhs )
|
|
|
|
|
{
|
|
|
|
|
this->assign( static_cast<base const&>(rhs) ) ;
|
|
|
|
|
return *this ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Assigns from a T (deep-copies the rhs value)
|
|
|
|
|
// Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
|
|
|
|
|