Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:43:19

0001 // Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
0002 // Copyright (C) 2014-2016 Andrzej Krzemienski.
0003 //
0004 // Use, modification, and distribution is subject to the Boost Software
0005 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt)
0007 //
0008 // See http://www.boost.org/libs/optional for documentation.
0009 //
0010 // You are welcome to contact the maintainer at:
0011 //  akrzemi1@gmail.com
0012 
0013 #ifndef BOOST_OPTIONAL_DETAIL_OLD_OPTIONAL_IMPLEMENTATION_AJK_28JAN2015_HPP
0014 #define BOOST_OPTIONAL_DETAIL_OLD_OPTIONAL_IMPLEMENTATION_AJK_28JAN2015_HPP
0015 
0016 #include <boost/detail/reference_content.hpp>
0017 #include <boost/type_traits/is_reference.hpp>
0018 #include <boost/type_traits/integral_constant.hpp>
0019 #include <boost/type_traits/conditional.hpp>
0020 #include <boost/core/invoke_swap.hpp>
0021 
0022 namespace boost {
0023 
0024 namespace optional_detail {
0025 
0026 
0027 template<class T>
0028 struct types_when_isnt_ref
0029 {
0030   typedef T const& reference_const_type ;
0031   typedef T &      reference_type ;
0032 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0033   typedef T &&     rval_reference_type ;
0034   typedef T &&     reference_type_of_temporary_wrapper;
0035 #ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
0036   // GCC 4.4 has support for an early draft of rvalue references. The conforming version below
0037   // causes warnings about returning references to a temporary.
0038   static T&& move(T&& r) { return r; }
0039 #else
0040   static rval_reference_type move(reference_type r) { return boost::move(r); }
0041 #endif
0042 #endif
0043   typedef T const* pointer_const_type ;
0044   typedef T *      pointer_type ;
0045   typedef T const& argument_type ;
0046 } ;
0047 
0048 template<class T>
0049 struct types_when_is_ref
0050 {
0051   typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type raw_type ;
0052 
0053   typedef raw_type&  reference_const_type ;
0054   typedef raw_type&  reference_type ;
0055 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0056   typedef BOOST_DEDUCED_TYPENAME remove_const<raw_type>::type&& rval_reference_type ;
0057   typedef raw_type&  reference_type_of_temporary_wrapper;
0058   static reference_type move(reference_type r) { return r; }
0059 #endif
0060   typedef raw_type*  pointer_const_type ;
0061   typedef raw_type*  pointer_type ;
0062   typedef raw_type&  argument_type ;
0063 } ;
0064 
0065 template <class To, class From>
0066 void prevent_binding_rvalue_ref_to_optional_lvalue_ref()
0067 {
0068 #ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES
0069   BOOST_STATIC_ASSERT_MSG(
0070     !boost::is_lvalue_reference<To>::value || !boost::is_rvalue_reference<From>::value, 
0071     "binding rvalue references to optional lvalue references is disallowed");
0072 #endif    
0073 }
0074 
0075 struct optional_tag {} ;
0076 
0077 template<class T>
0078 class optional_base : public optional_tag
0079 {
0080   private :
0081 
0082     typedef
0083 #if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564))
0084     BOOST_DEDUCED_TYPENAME
0085 #endif
0086     ::boost::detail::make_reference_content<T>::type internal_type ;
0087 
0088     typedef aligned_storage<internal_type> storage_type ;
0089 
0090     typedef types_when_isnt_ref<T> types_when_not_ref ;
0091     typedef types_when_is_ref<T>   types_when_ref   ;
0092 
0093     typedef optional_base<T> this_type ;
0094 
0095   protected :
0096 
0097     typedef T value_type ;
0098 
0099     typedef true_type  is_reference_tag ;
0100     typedef false_type is_not_reference_tag ;
0101 
0102     typedef BOOST_DEDUCED_TYPENAME is_reference<T>::type is_reference_predicate ;
0103 
0104   public:
0105     typedef BOOST_DEDUCED_TYPENAME conditional<is_reference_predicate::value,types_when_ref,types_when_not_ref>::type types ;
0106 
0107   protected:
0108     typedef BOOST_DEDUCED_TYPENAME types::reference_type       reference_type ;
0109     typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ;
0110 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0111     typedef BOOST_DEDUCED_TYPENAME types::rval_reference_type  rval_reference_type ;
0112     typedef BOOST_DEDUCED_TYPENAME types::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ;
0113 #endif
0114     typedef BOOST_DEDUCED_TYPENAME types::pointer_type         pointer_type ;
0115     typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type   pointer_const_type ;
0116     typedef BOOST_DEDUCED_TYPENAME types::argument_type        argument_type ;
0117 
0118     // Creates an optional<T> uninitialized.
0119     // No-throw
0120     optional_base()
0121       :
0122       m_initialized(false) {}
0123 
0124     // Creates an optional<T> uninitialized.
0125     // No-throw
0126     optional_base ( none_t )
0127       :
0128       m_initialized(false) {}
0129 
0130     // Creates an optional<T> initialized with 'val'.
0131     // Can throw if T::T(T const&) does
0132     optional_base ( argument_type val )
0133       :
0134       m_initialized(false)
0135     {
0136         construct(val);
0137     }
0138 
0139 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0140     // move-construct an optional<T> initialized from an rvalue-ref to 'val'.
0141     // Can throw if T::T(T&&) does
0142     optional_base ( rval_reference_type val )
0143       :
0144       m_initialized(false)
0145     {
0146       construct( boost::move(val) );
0147     }
0148 #endif
0149 
0150     // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional<T>.
0151     // Can throw if T::T(T const&) does
0152     optional_base ( bool cond, argument_type val )
0153       :
0154       m_initialized(false)
0155     {
0156       if ( cond )
0157         construct(val);
0158     }
0159 
0160     // Creates a deep copy of another optional<T>
0161     // Can throw if T::T(T const&) does
0162     optional_base ( optional_base const& rhs )
0163       :
0164       m_initialized(false)
0165     {
0166       if ( rhs.is_initialized() )
0167         construct(rhs.get_impl());
0168     }
0169 
0170 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0171     // Creates a deep move of another optional<T>
0172     // Can throw if T::T(T&&) does
0173     optional_base ( optional_base&& rhs )
0174       :
0175       m_initialized(false)
0176     {
0177       if ( rhs.is_initialized() )
0178         construct( boost::move(rhs.get_impl()) );
0179     }
0180 #endif
0181 
0182 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0183 
0184     template<class Expr, class PtrExpr>
0185     explicit optional_base ( Expr&& expr, PtrExpr const* tag )
0186       :
0187       m_initialized(false)
0188     {
0189       construct(boost::forward<Expr>(expr),tag);
0190     }
0191 
0192 #else
0193     // This is used for both converting and in-place constructions.
0194     // Derived classes use the 'tag' to select the appropriate
0195     // implementation (the correct 'construct()' overload)
0196     template<class Expr>
0197     explicit optional_base ( Expr const& expr, Expr const* tag )
0198       :
0199       m_initialized(false)
0200     {
0201       construct(expr,tag);
0202     }
0203 
0204 #endif
0205 
0206 
0207     // No-throw (assuming T::~T() doesn't)
0208     ~optional_base() { destroy() ; }
0209 
0210     // Assigns from another optional<T> (deep-copies the rhs value)
0211     void assign ( optional_base const& rhs )
0212     {
0213       if (is_initialized())
0214       {
0215         if ( rhs.is_initialized() )
0216              assign_value(rhs.get_impl(), is_reference_predicate() );
0217         else destroy();
0218       }
0219       else
0220       {
0221         if ( rhs.is_initialized() )
0222           construct(rhs.get_impl());
0223       }
0224     }
0225     
0226 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0227     // Assigns from another optional<T> (deep-moves the rhs value)
0228     void assign ( optional_base&& rhs )
0229     {
0230       if (is_initialized())
0231       {
0232         if ( rhs.is_initialized() )
0233              assign_value(boost::move(rhs.get_impl()), is_reference_predicate() );
0234         else destroy();
0235       }
0236       else
0237       {
0238         if ( rhs.is_initialized() )
0239           construct(boost::move(rhs.get_impl()));
0240       }
0241     }
0242 #endif 
0243 
0244     // Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
0245     template<class U>
0246     void assign ( optional<U> const& rhs )
0247     {
0248       if (is_initialized())
0249       {
0250         if ( rhs.is_initialized() )
0251 #ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
0252           assign_value(rhs.get(), is_reference_predicate() );
0253 #else
0254           assign_value(static_cast<value_type>(rhs.get()), is_reference_predicate() );
0255 #endif
0256           
0257         else destroy();
0258       }
0259       else
0260       {
0261         if ( rhs.is_initialized() )
0262 #ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
0263           construct(rhs.get());
0264 #else
0265           construct(static_cast<value_type>(rhs.get()));
0266 #endif
0267       }
0268     }
0269 
0270 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0271     // move-assigns from another _convertible_ optional<U> (deep-moves from the rhs value)
0272     template<class U>
0273     void assign ( optional<U>&& rhs )
0274     {
0275       typedef BOOST_DEDUCED_TYPENAME optional<U>::rval_reference_type ref_type;
0276       if (is_initialized())
0277       {
0278         if ( rhs.is_initialized() )
0279              assign_value(static_cast<ref_type>(rhs.get()), is_reference_predicate() );
0280         else destroy();
0281       }
0282       else
0283       {
0284         if ( rhs.is_initialized() )
0285           construct(static_cast<ref_type>(rhs.get()));
0286       }
0287     }
0288 #endif
0289     
0290     // Assigns from a T (deep-copies the rhs value)
0291     void assign ( argument_type val )
0292     {
0293       if (is_initialized())
0294            assign_value(val, is_reference_predicate() );
0295       else construct(val);
0296     }
0297     
0298 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0299     // Assigns from a T (deep-moves the rhs value)
0300     void assign ( rval_reference_type val )
0301     {
0302       if (is_initialized())
0303            assign_value( boost::move(val), is_reference_predicate() );
0304       else construct( boost::move(val) );
0305     }
0306 #endif
0307 
0308     // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
0309     // No-throw (assuming T::~T() doesn't)
0310     void assign ( none_t ) BOOST_NOEXCEPT { destroy(); }
0311 
0312 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
0313 
0314 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0315     template<class Expr, class ExprPtr>
0316     void assign_expr ( Expr&& expr, ExprPtr const* tag )
0317     {
0318       if (is_initialized())
0319         assign_expr_to_initialized(boost::forward<Expr>(expr),tag);
0320       else construct(boost::forward<Expr>(expr),tag);
0321     }
0322 #else
0323     template<class Expr>
0324     void assign_expr ( Expr const& expr, Expr const* tag )
0325     {
0326       if (is_initialized())
0327         assign_expr_to_initialized(expr,tag);
0328       else construct(expr,tag);
0329     }
0330 #endif
0331 
0332 #endif
0333 
0334   public :
0335 
0336     // Destroys the current value, if any, leaving this UNINITIALIZED
0337     // No-throw (assuming T::~T() doesn't)
0338     void reset() BOOST_NOEXCEPT { destroy(); }
0339 
0340     // **DEPRECATED** Replaces the current value -if any- with 'val'
0341     void reset ( argument_type val ) { assign(val); }
0342 
0343     // Returns a pointer to the value if this is initialized, otherwise,
0344     // returns NULL.
0345     // No-throw
0346     pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
0347     pointer_type       get_ptr()       { return m_initialized ? get_ptr_impl() : 0 ; }
0348 
0349     bool is_initialized() const { return m_initialized ; }
0350 
0351   protected :
0352 
0353     void construct ( argument_type val )
0354      {
0355        ::new (m_storage.address()) internal_type(val) ;
0356        m_initialized = true ;
0357      }
0358      
0359 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0360     void construct ( rval_reference_type val )
0361      {
0362        ::new (m_storage.address()) internal_type( types::move(val) ) ;
0363        m_initialized = true ;
0364      }
0365 #endif
0366 
0367 
0368 #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
0369     // Constructs in-place
0370     // upon exception *this is always uninitialized
0371     template<class... Args>
0372     void emplace_assign ( Args&&... args )
0373      {
0374        destroy();
0375        ::new (m_storage.address()) internal_type( boost::forward<Args>(args)... );
0376        m_initialized = true ;
0377      }
0378 #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
0379     template<class Arg>
0380     void emplace_assign ( Arg&& arg )
0381      {
0382        destroy();
0383        ::new (m_storage.address()) internal_type( boost::forward<Arg>(arg) );
0384        m_initialized = true ;
0385      }
0386      
0387     void emplace_assign ()
0388      {
0389        destroy();
0390        ::new (m_storage.address()) internal_type();
0391        m_initialized = true ;
0392      }
0393 #else
0394     template<class Arg>
0395     void emplace_assign ( const Arg& arg )
0396      {
0397        destroy();
0398        ::new (m_storage.address()) internal_type( arg );
0399        m_initialized = true ;
0400      }
0401      
0402     template<class Arg>
0403     void emplace_assign ( Arg& arg )
0404      {
0405        destroy();
0406        ::new (m_storage.address()) internal_type( arg );
0407        m_initialized = true ;
0408      }
0409      
0410     void emplace_assign ()
0411      {
0412        destroy();
0413        ::new (m_storage.address()) internal_type();
0414        m_initialized = true ;
0415      }
0416 #endif
0417 
0418 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
0419 
0420 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0421     // Constructs in-place using the given factory
0422     template<class Expr>
0423     void construct ( Expr&& factory, in_place_factory_base const* )
0424      {
0425        BOOST_STATIC_ASSERT ( !is_reference_predicate::value ) ;
0426        boost_optional_detail::construct<value_type>(factory, m_storage.address());
0427        m_initialized = true ;
0428      }
0429 
0430     // Constructs in-place using the given typed factory
0431     template<class Expr>
0432     void construct ( Expr&& factory, typed_in_place_factory_base const* )
0433      {
0434        BOOST_STATIC_ASSERT ( !is_reference_predicate::value ) ;
0435        factory.apply(m_storage.address()) ;
0436        m_initialized = true ;
0437      }
0438 
0439     template<class Expr>
0440     void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag )
0441      {
0442        destroy();
0443        construct(factory,tag);
0444      }
0445 
0446     // Constructs in-place using the given typed factory
0447     template<class Expr>
0448     void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag )
0449      {
0450        destroy();
0451        construct(factory,tag);
0452      }
0453 
0454 #else
0455     // Constructs in-place using the given factory
0456     template<class Expr>
0457     void construct ( Expr const& factory, in_place_factory_base const* )
0458      {
0459        BOOST_STATIC_ASSERT ( !is_reference_predicate::value ) ;
0460        boost_optional_detail::construct<value_type>(factory, m_storage.address());
0461        m_initialized = true ;
0462      }
0463 
0464     // Constructs in-place using the given typed factory
0465     template<class Expr>
0466     void construct ( Expr const& factory, typed_in_place_factory_base const* )
0467      {
0468        BOOST_STATIC_ASSERT ( !is_reference_predicate::value ) ;
0469        factory.apply(m_storage.address()) ;
0470        m_initialized = true ;
0471      }
0472 
0473     template<class Expr>
0474     void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag )
0475      {
0476        destroy();
0477        construct(factory,tag);
0478      }
0479 
0480     // Constructs in-place using the given typed factory
0481     template<class Expr>
0482     void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag )
0483      {
0484        destroy();
0485        construct(factory,tag);
0486      }
0487 #endif
0488 
0489 #endif
0490 
0491 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0492     // Constructs using any expression implicitly convertible to the single argument
0493     // of a one-argument T constructor.
0494     // Converting constructions of optional<T> from optional<U> uses this function with
0495     // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
0496     template<class Expr>
0497     void construct ( Expr&& expr, void const* )
0498     {
0499       new (m_storage.address()) internal_type(boost::forward<Expr>(expr)) ;
0500       m_initialized = true ;
0501     }
0502 
0503     // Assigns using a form any expression implicitly convertible to the single argument
0504     // of a T's assignment operator.
0505     // Converting assignments of optional<T> from optional<U> uses this function with
0506     // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
0507     template<class Expr>
0508     void assign_expr_to_initialized ( Expr&& expr, void const* )
0509     {
0510       assign_value(boost::forward<Expr>(expr), is_reference_predicate());
0511     }
0512 #else
0513     // Constructs using any expression implicitly convertible to the single argument
0514     // of a one-argument T constructor.
0515     // Converting constructions of optional<T> from optional<U> uses this function with
0516     // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
0517     template<class Expr>
0518     void construct ( Expr const& expr, void const* )
0519      {
0520        new (m_storage.address()) internal_type(expr) ;
0521        m_initialized = true ;
0522      }
0523 
0524     // Assigns using a form any expression implicitly convertible to the single argument
0525     // of a T's assignment operator.
0526     // Converting assignments of optional<T> from optional<U> uses this function with
0527     // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
0528     template<class Expr>
0529     void assign_expr_to_initialized ( Expr const& expr, void const* )
0530      {
0531        assign_value(expr, is_reference_predicate());
0532      }
0533 
0534 #endif
0535 
0536 #ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
0537     // BCB5.64 (and probably lower versions) workaround.
0538     //   The in-place factories are supported by means of catch-all constructors
0539     //   and assignment operators (the functions are parameterized in terms of
0540     //   an arbitrary 'Expr' type)
0541     //   This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U>
0542     //   to the 'Expr'-taking functions even though explicit overloads are present for them.
0543     //   Thus, the following overload is needed to properly handle the case when the 'lhs'
0544     //   is another optional.
0545     //
0546     // For VC<=70 compilers this workaround doesn't work because the compiler issues and error
0547     // instead of choosing the wrong overload
0548     //
0549 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0550     // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
0551     template<class Expr>
0552     void construct ( Expr&& expr, optional_tag const* )
0553      {
0554        if ( expr.is_initialized() )
0555        {
0556          // An exception can be thrown here.
0557          // It it happens, THIS will be left uninitialized.
0558          new (m_storage.address()) internal_type(types::move(expr.get())) ;
0559          m_initialized = true ;
0560        }
0561      }
0562 #else
0563     // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
0564     template<class Expr>
0565     void construct ( Expr const& expr, optional_tag const* )
0566      {
0567        if ( expr.is_initialized() )
0568        {
0569          // An exception can be thrown here.
0570          // It it happens, THIS will be left uninitialized.
0571          new (m_storage.address()) internal_type(expr.get()) ;
0572          m_initialized = true ;
0573        }
0574      }
0575 #endif
0576 #endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
0577 
0578     void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; }
0579     void assign_value ( argument_type val, is_reference_tag     ) { construct(val); }
0580 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0581     void assign_value ( rval_reference_type val, is_not_reference_tag ) { get_impl() = static_cast<rval_reference_type>(val); }
0582     void assign_value ( rval_reference_type val, is_reference_tag     ) { construct( static_cast<rval_reference_type>(val) ); }
0583 #endif
0584 
0585     void destroy()
0586     {
0587       if ( m_initialized )
0588         destroy_impl(is_reference_predicate()) ;
0589     }
0590 
0591     reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; }
0592     reference_type       get_impl()       { return dereference(get_object(), is_reference_predicate() ) ; }
0593 
0594     pointer_const_type get_ptr_impl() const { return cast_ptr(get_object(), is_reference_predicate() ) ; }
0595     pointer_type       get_ptr_impl()       { return cast_ptr(get_object(), is_reference_predicate() ) ; }
0596 
0597   private :
0598 
0599     // internal_type can be either T or reference_content<T>
0600 #if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
0601     // This workaround is supposed to silence GCC warnings about broken strict aliasing rules
0602     internal_type const* get_object() const
0603     {
0604         union { void const* ap_pvoid; internal_type const* as_ptype; } caster = { m_storage.address() };
0605         return caster.as_ptype;
0606     }
0607     internal_type *      get_object()
0608     {
0609         union { void* ap_pvoid; internal_type* as_ptype; } caster = { m_storage.address() };
0610         return caster.as_ptype;
0611     }
0612 #else
0613     internal_type const* get_object() const { return static_cast<internal_type const*>(m_storage.address()); }
0614     internal_type *      get_object()       { return static_cast<internal_type *>     (m_storage.address()); }
0615 #endif
0616 
0617     // reference_content<T> lacks an implicit conversion to T&, so the following is needed to obtain a proper reference.
0618     reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; }
0619     reference_type       dereference( internal_type*       p, is_not_reference_tag )       { return *p ; }
0620     reference_const_type dereference( internal_type const* p, is_reference_tag     ) const { return p->get() ; }
0621     reference_type       dereference( internal_type*       p, is_reference_tag     )       { return p->get() ; }
0622 
0623 #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x581))
0624     void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; }
0625 #else
0626     void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->~T() ; m_initialized = false ; }
0627 #endif
0628 
0629     void destroy_impl ( is_reference_tag     ) { m_initialized = false ; }
0630 
0631     // If T is of reference type, trying to get a pointer to the held value must result in a compile-time error.
0632     // Decent compilers should disallow conversions from reference_content<T>* to T*, but just in case,
0633     // the following overloads are used to filter out the case and guarantee an error in case of T being a reference.
0634     pointer_const_type cast_ptr( internal_type const* p, is_not_reference_tag ) const { return p ; }
0635     pointer_type       cast_ptr( internal_type *      p, is_not_reference_tag )       { return p ; }
0636     pointer_const_type cast_ptr( internal_type const* p, is_reference_tag     ) const { return &p->get() ; }
0637     pointer_type       cast_ptr( internal_type *      p, is_reference_tag     )       { return &p->get() ; }
0638 
0639     bool m_initialized ;
0640     storage_type m_storage ;
0641 } ;
0642 
0643 } // namespace optional_detail
0644 
0645 template<class T>
0646 class optional : public optional_detail::optional_base<T>
0647 {
0648     typedef optional_detail::optional_base<T> base ;
0649 
0650   public :
0651 
0652     typedef optional<T> this_type ;
0653 
0654     typedef BOOST_DEDUCED_TYPENAME base::value_type           value_type ;
0655     typedef BOOST_DEDUCED_TYPENAME base::reference_type       reference_type ;
0656     typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
0657 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0658     typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type  rval_reference_type ;
0659     typedef BOOST_DEDUCED_TYPENAME base::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ;
0660 #endif
0661     typedef BOOST_DEDUCED_TYPENAME base::pointer_type         pointer_type ;
0662     typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type   pointer_const_type ;
0663     typedef BOOST_DEDUCED_TYPENAME base::argument_type        argument_type ;
0664 
0665     // Creates an optional<T> uninitialized.
0666     // No-throw
0667     optional() BOOST_NOEXCEPT : base() {}
0668 
0669     // Creates an optional<T> uninitialized.
0670     // No-throw
0671     optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {}
0672 
0673     // Creates an optional<T> initialized with 'val'.
0674     // Can throw if T::T(T const&) does
0675     optional ( argument_type val ) : base(val) {}
0676 
0677 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0678     // Creates an optional<T> initialized with 'move(val)'.
0679     // Can throw if T::T(T &&) does
0680     optional ( rval_reference_type val ) : base( boost::forward<T>(val) ) 
0681       {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();}
0682 #endif
0683 
0684     // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
0685     // Can throw if T::T(T const&) does
0686     optional ( bool cond, argument_type val ) : base(cond,val) {}
0687 
0688     // NOTE: MSVC needs templated versions first
0689 
0690     // Creates a deep copy of another convertible optional<U>
0691     // Requires a valid conversion from U to T.
0692     // Can throw if T::T(U const&) does
0693     template<class U>
0694     explicit optional ( optional<U> const& rhs )
0695       :
0696       base()
0697     {
0698       if ( rhs.is_initialized() )
0699         this->construct(rhs.get());
0700     }
0701     
0702 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0703     // Creates a deep move of another convertible optional<U>
0704     // Requires a valid conversion from U to T.
0705     // Can throw if T::T(U&&) does
0706     template<class U>
0707     explicit optional ( optional<U> && rhs )
0708       :
0709       base()
0710     {
0711       if ( rhs.is_initialized() )
0712         this->construct( boost::move(rhs.get()) );
0713     }
0714 #endif
0715 
0716 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
0717     // Creates an optional<T> with an expression which can be either
0718     //  (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
0719     //  (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
0720     //  (c) Any expression implicitly convertible to the single type
0721     //      of a one-argument T's constructor.
0722     //  (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
0723     //       even though explicit overloads are present for these.
0724     // Depending on the above some T ctor is called.
0725     // Can throw if the resolved T ctor throws.
0726 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0727 
0728 
0729   template<class Expr>
0730   explicit optional ( Expr&& expr, 
0731                       BOOST_DEDUCED_TYPENAME boost::disable_if_c<
0732                         (boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value) || 
0733                         boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value, bool >::type = true 
0734   ) 
0735     : base(boost::forward<Expr>(expr),boost::addressof(expr)) 
0736     {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, Expr&&>();}
0737 
0738 #else
0739     template<class Expr>
0740     explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
0741 #endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0742 #endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
0743 
0744     // Creates a deep copy of another optional<T>
0745     // Can throw if T::T(T const&) does
0746     optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
0747 
0748 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0749     // Creates a deep move of another optional<T>
0750     // Can throw if T::T(T&&) does
0751     optional ( optional && rhs )
0752       BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
0753       : base( boost::move(rhs) )
0754     {}
0755 
0756 #endif
0757    // No-throw (assuming T::~T() doesn't)
0758     ~optional() {}
0759 
0760 #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
0761     // Assigns from an expression. See corresponding constructor.
0762     // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
0763 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0764 
0765     template<class Expr>
0766     BOOST_DEDUCED_TYPENAME boost::disable_if_c<
0767       boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value || 
0768         boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value,
0769       optional&
0770     >::type 
0771     operator= ( Expr&& expr )
0772       {
0773         optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, Expr&&>();
0774         this->assign_expr(boost::forward<Expr>(expr),boost::addressof(expr));
0775         return *this ;
0776       }
0777 
0778 #else
0779     template<class Expr>
0780     optional& operator= ( Expr const& expr )
0781       {
0782         this->assign_expr(expr,boost::addressof(expr));
0783         return *this ;
0784       }
0785 #endif // !defined  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0786 #endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
0787 
0788     // Copy-assigns from another convertible optional<U> (converts && deep-copies the rhs value)
0789     // Requires a valid conversion from U to T.
0790     // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
0791     template<class U>
0792     optional& operator= ( optional<U> const& rhs )
0793       {
0794         this->assign(rhs);
0795         return *this ;
0796       }
0797       
0798 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0799     // Move-assigns from another convertible optional<U> (converts && deep-moves the rhs value)
0800     // Requires a valid conversion from U to T.
0801     // Basic Guarantee: If T::T( U && ) throws, this is left UNINITIALIZED
0802     template<class U>
0803     optional& operator= ( optional<U> && rhs )
0804       {
0805         this->assign(boost::move(rhs));
0806         return *this ;
0807       }
0808 #endif
0809 
0810     // Assigns from another optional<T> (deep-copies the rhs value)
0811     // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
0812     //  (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
0813     optional& operator= ( optional const& rhs )
0814       {
0815         this->assign( static_cast<base const&>(rhs) ) ;
0816         return *this ;
0817       }
0818 
0819 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0820     // Assigns from another optional<T> (deep-moves the rhs value)
0821     optional& operator= ( optional && rhs ) 
0822       BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
0823       {
0824         this->assign( static_cast<base &&>(rhs) ) ;
0825         return *this ;
0826       }
0827 #endif
0828 
0829     // Assigns from a T (deep-copies the rhs value)
0830     // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
0831     optional& operator= ( argument_type val )
0832       {
0833         this->assign( val ) ;
0834         return *this ;
0835       }
0836 
0837 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0838     // Assigns from a T (deep-moves the rhs value)
0839     optional& operator= ( rval_reference_type val )
0840       {
0841         optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();
0842         this->assign( boost::move(val) ) ;
0843         return *this ;
0844       }
0845 #endif
0846 
0847     // Assigns from a "none"
0848     // Which destroys the current value, if any, leaving this UNINITIALIZED
0849     // No-throw (assuming T::~T() doesn't)
0850     optional& operator= ( none_t none_ ) BOOST_NOEXCEPT
0851       {
0852         this->assign( none_ ) ;
0853         return *this ;
0854       }
0855       
0856 #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
0857     // Constructs in-place
0858     // upon exception *this is always uninitialized
0859     template<class... Args>
0860     void emplace ( Args&&... args )
0861      {
0862        this->emplace_assign( boost::forward<Args>(args)... );
0863      }
0864 #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
0865     template<class Arg>
0866     void emplace ( Arg&& arg )
0867      {
0868        this->emplace_assign( boost::forward<Arg>(arg) );
0869      }
0870      
0871     void emplace ()
0872      {
0873        this->emplace_assign();
0874      }
0875 #else
0876     template<class Arg>
0877     void emplace ( const Arg& arg )
0878      {
0879        this->emplace_assign( arg );
0880      }
0881      
0882     template<class Arg>
0883     void emplace ( Arg& arg )
0884      {
0885        this->emplace_assign( arg );
0886      }
0887      
0888     void emplace ()
0889      {
0890        this->emplace_assign();
0891      }
0892 #endif
0893 
0894     void swap( optional & arg )
0895       BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
0896       {
0897         // allow for Koenig lookup
0898         boost::core::invoke_swap(*this, arg);
0899       }
0900 
0901 
0902     // Returns a reference to the value if this is initialized, otherwise,
0903     // the behaviour is UNDEFINED
0904     // No-throw
0905     reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
0906     reference_type       get()       { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
0907 
0908     // Returns a copy of the value if this is initialized, 'v' otherwise
0909     reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
0910     reference_type       get_value_or ( reference_type       v )       { return this->is_initialized() ? get() : v ; }
0911 
0912     // Returns a pointer to the value if this is initialized, otherwise,
0913     // the behaviour is UNDEFINED
0914     // No-throw
0915     pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
0916     pointer_type       operator->()       { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
0917 
0918     // Returns a reference to the value if this is initialized, otherwise,
0919     // the behaviour is UNDEFINED
0920     // No-throw
0921 #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) 
0922     reference_const_type operator *() const& { return this->get() ; }
0923     reference_type       operator *() &      { return this->get() ; }
0924     reference_type_of_temporary_wrapper operator *() && { return base::types::move(this->get()) ; }
0925 #else
0926     reference_const_type operator *() const { return this->get() ; }
0927     reference_type       operator *()       { return this->get() ; }
0928 #endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS
0929 
0930 #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) 
0931     reference_const_type value() const&
0932       { 
0933         if (this->is_initialized())
0934           return this->get() ;
0935         else
0936           throw_exception(bad_optional_access());
0937       }
0938       
0939     reference_type value() &
0940       { 
0941         if (this->is_initialized())
0942           return this->get() ;
0943         else
0944           throw_exception(bad_optional_access());
0945       }
0946       
0947     reference_type_of_temporary_wrapper value() &&
0948       { 
0949         if (this->is_initialized())
0950           return base::types::move(this->get()) ;
0951         else
0952           throw_exception(bad_optional_access());
0953       }
0954 
0955 #else 
0956     reference_const_type value() const
0957       { 
0958         if (this->is_initialized())
0959           return this->get() ;
0960         else
0961           throw_exception(bad_optional_access());
0962       }
0963       
0964     reference_type value()
0965       { 
0966         if (this->is_initialized())
0967           return this->get() ;
0968         else
0969           throw_exception(bad_optional_access());
0970       }
0971 #endif
0972 
0973 
0974 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
0975     template <class U>
0976     value_type value_or ( U&& v ) const&
0977       { 
0978         if (this->is_initialized())
0979           return get();
0980         else
0981           return boost::forward<U>(v);
0982       }
0983     
0984     template <class U>
0985     value_type value_or ( U&& v ) && 
0986       { 
0987         if (this->is_initialized())
0988           return base::types::move(get());
0989         else
0990           return boost::forward<U>(v);
0991       }
0992 #elif !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
0993     template <class U>
0994     value_type value_or ( U&& v ) const 
0995       {
0996         if (this->is_initialized())
0997           return get();
0998         else
0999           return boost::forward<U>(v);
1000       }
1001 #else
1002     template <class U>
1003     value_type value_or ( U const& v ) const 
1004       { 
1005         if (this->is_initialized())
1006           return get();
1007         else
1008           return v;
1009       }
1010       
1011     template <class U>
1012     value_type value_or ( U& v ) const 
1013       { 
1014         if (this->is_initialized())
1015           return get();
1016         else
1017           return v;
1018       }
1019 #endif
1020 
1021 
1022 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
1023     template <typename F>
1024     value_type value_or_eval ( F f ) const&
1025       {
1026         if (this->is_initialized())
1027           return get();
1028         else
1029           return f();
1030       }
1031       
1032     template <typename F>
1033     value_type value_or_eval ( F f ) &&
1034       {
1035         if (this->is_initialized())
1036           return base::types::move(get());
1037         else
1038           return f();
1039       }
1040 #else
1041     template <typename F>
1042     value_type value_or_eval ( F f ) const
1043       {
1044         if (this->is_initialized())
1045           return get();
1046         else
1047           return f();
1048       }
1049 #endif
1050       
1051     bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; }
1052     
1053     BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
1054 } ;
1055 
1056 } // namespace boost
1057 
1058 
1059 #endif // header guard