You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
500 lines
14 KiB
500 lines
14 KiB
3 years ago
|
// trivilally-copyable version of the storage
|
||
|
|
||
|
template<class T>
|
||
|
class tc_optional_base : public optional_tag
|
||
|
{
|
||
|
private :
|
||
|
|
||
|
typedef tc_optional_base<T> this_type ;
|
||
|
|
||
|
protected :
|
||
|
|
||
|
typedef T value_type ;
|
||
|
|
||
|
protected:
|
||
|
typedef T & reference_type ;
|
||
|
typedef T const& reference_const_type ;
|
||
|
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||
|
typedef T && rval_reference_type ;
|
||
|
typedef T && reference_type_of_temporary_wrapper ;
|
||
|
#endif
|
||
|
typedef T * pointer_type ;
|
||
|
typedef T const* pointer_const_type ;
|
||
|
typedef T const& argument_type ;
|
||
|
|
||
|
tc_optional_base()
|
||
|
:
|
||
|
m_initialized(false) {}
|
||
|
|
||
|
tc_optional_base ( none_t )
|
||
|
:
|
||
|
m_initialized(false) {}
|
||
|
|
||
|
tc_optional_base ( init_value_tag, argument_type val )
|
||
|
:
|
||
|
m_initialized(true), m_storage(val) {}
|
||
|
|
||
|
tc_optional_base ( bool cond, argument_type val )
|
||
|
:
|
||
|
m_initialized(cond), m_storage(val) {}
|
||
|
|
||
|
// tc_optional_base ( tc_optional_base const& ) = default;
|
||
|
|
||
|
|
||
|
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||
|
|
||
|
template<class Expr, class PtrExpr>
|
||
|
explicit tc_optional_base ( Expr&& expr, PtrExpr const* tag )
|
||
|
:
|
||
|
m_initialized(false)
|
||
|
{
|
||
|
construct(boost::forward<Expr>(expr),tag);
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
// This is used for both converting and in-place constructions.
|
||
|
// Derived classes use the 'tag' to select the appropriate
|
||
|
// implementation (the correct 'construct()' overload)
|
||
|
template<class Expr>
|
||
|
explicit tc_optional_base ( Expr const& expr, Expr const* tag )
|
||
|
:
|
||
|
m_initialized(false)
|
||
|
{
|
||
|
construct(expr,tag);
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
// tc_optional_base& operator= ( tc_optional_base const& ) = default;
|
||
|
// ~tc_optional_base() = default;
|
||
|
|
||
|
// Assigns from another optional<T> (deep-copies the rhs value)
|
||
|
void assign ( tc_optional_base const& rhs )
|
||
|
{
|
||
|
*this = rhs;
|
||
|
}
|
||
|
|
||
|
// Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
|
||
|
template<class U>
|
||
|
void assign ( optional<U> const& rhs )
|
||
|
{
|
||
|
if ( rhs.is_initialized() )
|
||
|
#ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
|
||
|
m_storage = rhs.get();
|
||
|
#else
|
||
|
m_storage = static_cast<value_type>(rhs.get());
|
||
|
#endif
|
||
|
|
||
|
m_initialized = rhs.is_initialized();
|
||
|
}
|
||
|
|
||
|
#ifndef BOOST_OPTIONAL_DETAIL_NO_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 ( rhs.is_initialized() )
|
||
|
m_storage = static_cast<ref_type>(rhs.get());
|
||
|
m_initialized = rhs.is_initialized();
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
void assign ( argument_type val )
|
||
|
{
|
||
|
construct(val);
|
||
|
}
|
||
|
|
||
|
void assign ( none_t ) { destroy(); }
|
||
|
|
||
|
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||
|
|
||
|
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||
|
template<class Expr, class ExprPtr>
|
||
|
void assign_expr ( Expr&& expr, ExprPtr const* tag )
|
||
|
{
|
||
|
construct(boost::forward<Expr>(expr),tag);
|
||
|
}
|
||
|
#else
|
||
|
template<class Expr>
|
||
|
void assign_expr ( Expr const& expr, Expr const* tag )
|
||
|
{
|
||
|
construct(expr,tag);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#endif
|
||
|
|
||
|
public :
|
||
|
|
||
|
// Destroys the current value, if any, leaving this UNINITIALIZED
|
||
|
// No-throw (assuming T::~T() doesn't)
|
||
|
void reset() BOOST_NOEXCEPT { destroy(); }
|
||
|
|
||
|
// **DEPPRECATED** Replaces the current value -if any- with 'val'
|
||
|
void reset ( argument_type val ) BOOST_NOEXCEPT { assign(val); }
|
||
|
|
||
|
// Returns a pointer to the value if this is initialized, otherwise,
|
||
|
// returns NULL.
|
||
|
// No-throw
|
||
|
pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
|
||
|
pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; }
|
||
|
|
||
|
bool is_initialized() const { return m_initialized ; }
|
||
|
|
||
|
protected :
|
||
|
|
||
|
void construct ( argument_type val )
|
||
|
{
|
||
|
m_storage = val ;
|
||
|
m_initialized = true ;
|
||
|
}
|
||
|
|
||
|
|
||
|
#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||
|
// Constructs in-place
|
||
|
// upon exception *this is always uninitialized
|
||
|
template<class... Args>
|
||
|
void construct ( in_place_init_t, Args&&... args )
|
||
|
{
|
||
|
m_storage = value_type( boost::forward<Args>(args)... ) ;
|
||
|
m_initialized = true ;
|
||
|
}
|
||
|
|
||
|
template<class... Args>
|
||
|
void emplace_assign ( Args&&... args )
|
||
|
{
|
||
|
construct(in_place_init, boost::forward<Args>(args)...);
|
||
|
}
|
||
|
|
||
|
template<class... Args>
|
||
|
explicit tc_optional_base ( in_place_init_t, Args&&... args )
|
||
|
:
|
||
|
m_initialized(false)
|
||
|
{
|
||
|
construct(in_place_init, boost::forward<Args>(args)...);
|
||
|
}
|
||
|
|
||
|
template<class... Args>
|
||
|
explicit tc_optional_base ( in_place_init_if_t, bool cond, Args&&... args )
|
||
|
:
|
||
|
m_initialized(false)
|
||
|
{
|
||
|
if ( cond )
|
||
|
construct(in_place_init, boost::forward<Args>(args)...);
|
||
|
}
|
||
|
#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
|
||
|
template<class Arg>
|
||
|
void construct ( in_place_init_t, Arg&& arg )
|
||
|
{
|
||
|
m_storage = value_type( boost::forward<Arg>(arg) );
|
||
|
m_initialized = true ;
|
||
|
}
|
||
|
|
||
|
void construct ( in_place_init_t )
|
||
|
{
|
||
|
m_storage = value_type();
|
||
|
m_initialized = true ;
|
||
|
}
|
||
|
|
||
|
template<class Arg>
|
||
|
void emplace_assign ( Arg&& arg )
|
||
|
{
|
||
|
construct(in_place_init, boost::forward<Arg>(arg)) ;
|
||
|
}
|
||
|
|
||
|
void emplace_assign ()
|
||
|
{
|
||
|
construct(in_place_init) ;
|
||
|
}
|
||
|
|
||
|
template<class Arg>
|
||
|
explicit tc_optional_base ( in_place_init_t, Arg&& arg )
|
||
|
:
|
||
|
m_initialized(false)
|
||
|
{
|
||
|
construct(in_place_init, boost::forward<Arg>(arg));
|
||
|
}
|
||
|
|
||
|
explicit tc_optional_base ( in_place_init_t )
|
||
|
:
|
||
|
m_initialized(false), m_storage() {}
|
||
|
|
||
|
template<class Arg>
|
||
|
explicit tc_optional_base ( in_place_init_if_t, bool cond, Arg&& arg )
|
||
|
:
|
||
|
m_initialized(false)
|
||
|
{
|
||
|
if ( cond )
|
||
|
construct(in_place_init, boost::forward<Arg>(arg));
|
||
|
}
|
||
|
|
||
|
explicit tc_optional_base ( in_place_init_if_t, bool cond )
|
||
|
:
|
||
|
m_initialized(false)
|
||
|
{
|
||
|
if ( cond )
|
||
|
construct(in_place_init);
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
|
||
|
template<class Arg>
|
||
|
void construct ( in_place_init_t, const Arg& arg )
|
||
|
{
|
||
|
m_storage = value_type( arg );
|
||
|
m_initialized = true ;
|
||
|
}
|
||
|
|
||
|
template<class Arg>
|
||
|
void construct ( in_place_init_t, Arg& arg )
|
||
|
{
|
||
|
m_storage = value_type( arg );
|
||
|
m_initialized = true ;
|
||
|
}
|
||
|
|
||
|
void construct ( in_place_init_t )
|
||
|
{
|
||
|
m_storage = value_type();
|
||
|
m_initialized = true ;
|
||
|
}
|
||
|
|
||
|
template<class Arg>
|
||
|
void emplace_assign ( const Arg& arg )
|
||
|
{
|
||
|
construct(in_place_init, arg);
|
||
|
}
|
||
|
|
||
|
template<class Arg>
|
||
|
void emplace_assign ( Arg& arg )
|
||
|
{
|
||
|
construct(in_place_init, arg);
|
||
|
}
|
||
|
|
||
|
void emplace_assign ()
|
||
|
{
|
||
|
construct(in_place_init);
|
||
|
}
|
||
|
|
||
|
template<class Arg>
|
||
|
explicit tc_optional_base ( in_place_init_t, const Arg& arg )
|
||
|
: m_initialized(false)
|
||
|
{
|
||
|
construct(in_place_init, arg);
|
||
|
}
|
||
|
|
||
|
template<class Arg>
|
||
|
explicit tc_optional_base ( in_place_init_t, Arg& arg )
|
||
|
: m_initialized(false)
|
||
|
{
|
||
|
construct(in_place_init, arg);
|
||
|
}
|
||
|
|
||
|
explicit tc_optional_base ( in_place_init_t )
|
||
|
: m_initialized(false)
|
||
|
{
|
||
|
construct(in_place_init);
|
||
|
}
|
||
|
|
||
|
template<class Arg>
|
||
|
explicit tc_optional_base ( in_place_init_if_t, bool cond, const Arg& arg )
|
||
|
: m_initialized(false)
|
||
|
{
|
||
|
if ( cond )
|
||
|
construct(in_place_init, arg);
|
||
|
}
|
||
|
|
||
|
template<class Arg>
|
||
|
explicit tc_optional_base ( in_place_init_if_t, bool cond, Arg& arg )
|
||
|
: m_initialized(false)
|
||
|
{
|
||
|
if ( cond )
|
||
|
construct(in_place_init, arg);
|
||
|
}
|
||
|
|
||
|
explicit tc_optional_base ( in_place_init_if_t, bool cond )
|
||
|
: m_initialized(false)
|
||
|
{
|
||
|
if ( cond )
|
||
|
construct(in_place_init);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||
|
|
||
|
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||
|
// Constructs in-place using the given factory
|
||
|
template<class Expr>
|
||
|
void construct ( Expr&& factory, in_place_factory_base const* )
|
||
|
{
|
||
|
boost_optional_detail::construct<value_type>(factory, boost::addressof(m_storage));
|
||
|
m_initialized = true ;
|
||
|
}
|
||
|
|
||
|
// Constructs in-place using the given typed factory
|
||
|
template<class Expr>
|
||
|
void construct ( Expr&& factory, typed_in_place_factory_base const* )
|
||
|
{
|
||
|
factory.apply(boost::addressof(m_storage)) ;
|
||
|
m_initialized = true ;
|
||
|
}
|
||
|
|
||
|
template<class Expr>
|
||
|
void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag )
|
||
|
{
|
||
|
destroy();
|
||
|
construct(factory,tag);
|
||
|
}
|
||
|
|
||
|
// Constructs in-place using the given typed factory
|
||
|
template<class Expr>
|
||
|
void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag )
|
||
|
{
|
||
|
destroy();
|
||
|
construct(factory,tag);
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
// Constructs in-place using the given factory
|
||
|
template<class Expr>
|
||
|
void construct ( Expr const& factory, in_place_factory_base const* )
|
||
|
{
|
||
|
boost_optional_detail::construct<value_type>(factory, boost::addressof(m_storage));
|
||
|
m_initialized = true ;
|
||
|
}
|
||
|
|
||
|
// Constructs in-place using the given typed factory
|
||
|
template<class Expr>
|
||
|
void construct ( Expr const& factory, typed_in_place_factory_base const* )
|
||
|
{
|
||
|
factory.apply(boost::addressof(m_storage)) ;
|
||
|
m_initialized = true ;
|
||
|
}
|
||
|
|
||
|
template<class Expr>
|
||
|
void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag )
|
||
|
{
|
||
|
destroy();
|
||
|
construct(factory,tag);
|
||
|
}
|
||
|
|
||
|
// Constructs in-place using the given typed factory
|
||
|
template<class Expr>
|
||
|
void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag )
|
||
|
{
|
||
|
destroy();
|
||
|
construct(factory,tag);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||
|
// Constructs using any expression implicitly convertible to the single argument
|
||
|
// of a one-argument T constructor.
|
||
|
// Converting constructions of optional<T> from optional<U> uses this function with
|
||
|
// 'Expr' being of type 'U' and relying on a converting constructor of T from U.
|
||
|
template<class Expr>
|
||
|
void construct ( Expr&& expr, void const* )
|
||
|
{
|
||
|
m_storage = value_type(boost::forward<Expr>(expr)) ;
|
||
|
m_initialized = true ;
|
||
|
}
|
||
|
|
||
|
// Assigns using a form any expression implicitly convertible to the single argument
|
||
|
// of a T's assignment operator.
|
||
|
// Converting assignments of optional<T> from optional<U> uses this function with
|
||
|
// 'Expr' being of type 'U' and relying on a converting assignment of T from U.
|
||
|
template<class Expr>
|
||
|
void assign_expr_to_initialized ( Expr&& expr, void const* )
|
||
|
{
|
||
|
assign_value( boost::forward<Expr>(expr) );
|
||
|
}
|
||
|
#else
|
||
|
// Constructs using any expression implicitly convertible to the single argument
|
||
|
// of a one-argument T constructor.
|
||
|
// Converting constructions of optional<T> from optional<U> uses this function with
|
||
|
// 'Expr' being of type 'U' and relying on a converting constructor of T from U.
|
||
|
template<class Expr>
|
||
|
void construct ( Expr const& expr, void const* )
|
||
|
{
|
||
|
m_storage = value_type(expr) ;
|
||
|
m_initialized = true ;
|
||
|
}
|
||
|
|
||
|
// Assigns using a form any expression implicitly convertible to the single argument
|
||
|
// of a T's assignment operator.
|
||
|
// Converting assignments of optional<T> from optional<U> uses this function with
|
||
|
// 'Expr' being of type 'U' and relying on a converting assignment of T from U.
|
||
|
template<class Expr>
|
||
|
void assign_expr_to_initialized ( Expr const& expr, void const* )
|
||
|
{
|
||
|
assign_value(expr);
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#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
|
||
|
//
|
||
|
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||
|
// Notice that 'Expr' will be optional<T> or optional<U> (but not tc_optional_base<..>)
|
||
|
template<class Expr>
|
||
|
void construct ( Expr&& expr, optional_tag const* )
|
||
|
{
|
||
|
if ( expr.is_initialized() )
|
||
|
{
|
||
|
// An exception can be thrown here.
|
||
|
// It it happens, THIS will be left uninitialized.
|
||
|
m_storage = value_type(boost::move(expr.get())) ;
|
||
|
m_initialized = true ;
|
||
|
}
|
||
|
}
|
||
|
#else
|
||
|
// Notice that 'Expr' will be optional<T> or optional<U> (but not tc_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.
|
||
|
m_storage = value_type(expr.get()) ;
|
||
|
m_initialized = true ;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
#endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
|
||
|
|
||
|
void assign_value ( argument_type val ) { m_storage = val; }
|
||
|
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||
|
void assign_value ( rval_reference_type val ) { m_storage = static_cast<rval_reference_type>(val); }
|
||
|
#endif
|
||
|
|
||
|
void destroy()
|
||
|
{
|
||
|
m_initialized = false;
|
||
|
}
|
||
|
|
||
|
reference_const_type get_impl() const { return m_storage ; }
|
||
|
reference_type get_impl() { return m_storage ; }
|
||
|
|
||
|
pointer_const_type get_ptr_impl() const { return boost::addressof(m_storage); }
|
||
|
pointer_type get_ptr_impl() { return boost::addressof(m_storage); }
|
||
|
|
||
|
private :
|
||
|
|
||
|
bool m_initialized ;
|
||
|
T m_storage ;
|
||
|
} ;
|