Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 08:53:34

0001 // Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
0002 // Copyright (C) 2014 - 2021 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 author at:
0011 //  fernando_cacciola@hotmail.com
0012 //
0013 // Revisions:
0014 // 27 Apr 2008 (improved swap) Fernando Cacciola, Niels Dekker, Thorsten Ottosen
0015 // 05 May 2014 (Added move semantics) Andrzej Krzemienski
0016 //
0017 #ifndef BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
0018 #define BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
0019 
0020 #include <new>
0021 #ifndef BOOST_NO_IOSTREAM
0022 #include <iosfwd>
0023 #endif // BOOST_NO_IOSTREAM
0024 
0025 #include <boost/assert.hpp>
0026 #include <boost/core/addressof.hpp>
0027 #include <boost/core/enable_if.hpp>
0028 #include <boost/core/invoke_swap.hpp>
0029 #include <boost/core/launder.hpp>
0030 #include <boost/optional/bad_optional_access.hpp>
0031 #include <boost/throw_exception.hpp>
0032 #include <boost/type_traits/alignment_of.hpp>
0033 #include <boost/type_traits/conditional.hpp>
0034 #include <boost/type_traits/conjunction.hpp>
0035 #include <boost/type_traits/disjunction.hpp>
0036 #include <boost/type_traits/has_nothrow_constructor.hpp>
0037 #include <boost/type_traits/type_with_alignment.hpp>
0038 #include <boost/type_traits/remove_const.hpp>
0039 #include <boost/type_traits/remove_reference.hpp>
0040 #include <boost/type_traits/decay.hpp>
0041 #include <boost/type_traits/is_assignable.hpp>
0042 #include <boost/type_traits/is_base_of.hpp>
0043 #include <boost/type_traits/is_const.hpp>
0044 #include <boost/type_traits/is_constructible.hpp>
0045 #include <boost/type_traits/is_convertible.hpp>
0046 #include <boost/type_traits/is_lvalue_reference.hpp>
0047 #include <boost/type_traits/is_nothrow_move_assignable.hpp>
0048 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
0049 #include <boost/type_traits/is_rvalue_reference.hpp>
0050 #include <boost/type_traits/is_same.hpp>
0051 #include <boost/type_traits/is_volatile.hpp>
0052 #include <boost/type_traits/is_scalar.hpp>
0053 #include <boost/none.hpp>
0054 
0055 #include <boost/optional/optional_fwd.hpp>
0056 #include <boost/optional/detail/optional_config.hpp>
0057 #include <boost/optional/detail/optional_factory_support.hpp>
0058 #include <boost/optional/detail/optional_aligned_storage.hpp>
0059 #include <boost/optional/detail/optional_hash.hpp>
0060 #include <boost/optional/detail/optional_utility.hpp>
0061 
0062 namespace boost { namespace optional_detail {
0063 
0064 template <typename T>
0065 struct optional_value_type
0066 {
0067 };
0068 
0069 template <typename U>
0070 struct optional_value_type< ::boost::optional<U> >
0071 {
0072   typedef U type;
0073 };
0074 
0075 template <typename T>
0076 T declval();
0077 
0078 
0079 // implementing my own result_of so that it works for C++11 (std::result_of)
0080 // and in C++20 (std::invoke_result).
0081 template <typename F, typename Ref, typename Rslt = decltype(declval<F>()(declval<Ref>()))>
0082 struct result_of
0083 {
0084   typedef Rslt type;
0085 };
0086 
0087 template <typename F, typename Ref, typename Rslt = typename optional_value_type<typename result_of<F, Ref>::type>::type>
0088 struct result_value_type
0089 {
0090   typedef Rslt type;
0091 };
0092 
0093 // optional<typename optional_detail::optional_value_type<decltype(optional_detail::declval<F>()(optional_detail::declval<reference_type>()))>::type>
0094 
0095 }} // namespace boost::optional_detail
0096 
0097 namespace boost {
0098 
0099 namespace optional_ns {
0100 
0101 // a tag for in-place initialization of contained value
0102 struct in_place_init_t
0103 {
0104   struct init_tag{};
0105   BOOST_CONSTEXPR explicit in_place_init_t(init_tag){}
0106 };
0107 BOOST_INLINE_CONSTEXPR in_place_init_t in_place_init ((in_place_init_t::init_tag()));
0108 
0109 // a tag for conditional in-place initialization of contained value
0110 struct in_place_init_if_t
0111 {
0112   struct init_tag{};
0113   BOOST_CONSTEXPR explicit in_place_init_if_t(init_tag){}
0114 };
0115 BOOST_INLINE_CONSTEXPR in_place_init_if_t in_place_init_if ((in_place_init_if_t::init_tag()));
0116 
0117 } // namespace optional_ns
0118 
0119 using optional_ns::in_place_init_t;
0120 using optional_ns::in_place_init;
0121 using optional_ns::in_place_init_if_t;
0122 using optional_ns::in_place_init_if;
0123 
0124 namespace optional_detail {
0125 
0126 struct init_value_tag {};
0127 
0128 struct optional_tag {};
0129 
0130 
0131 template<class T>
0132 class optional_base : public optional_tag
0133 {
0134   private :
0135 
0136     typedef aligned_storage<T> storage_type ;
0137     typedef optional_base<T> this_type ;
0138 
0139   protected :
0140 
0141     typedef T value_type ;
0142     typedef typename boost::remove_const<T>::type unqualified_value_type;
0143 
0144   protected:
0145     typedef T &       reference_type ;
0146     typedef T const&  reference_const_type ;
0147     typedef T &&  rval_reference_type ;
0148     typedef T &&  reference_type_of_temporary_wrapper ;
0149     typedef T *         pointer_type ;
0150     typedef T const*    pointer_const_type ;
0151     typedef T const&    argument_type ;
0152 
0153     // Creates an optional<T> uninitialized.
0154     // No-throw
0155     optional_base()
0156       :
0157       m_initialized(false) {}
0158 
0159     // Creates an optional<T> uninitialized.
0160     // No-throw
0161     optional_base ( none_t )
0162       :
0163       m_initialized(false) {}
0164 
0165     // Creates an optional<T> initialized with 'val'.
0166     // Can throw if T::T(T const&) does
0167     optional_base ( init_value_tag, argument_type val )
0168       :
0169       m_initialized(false)
0170     {
0171         construct(val);
0172     }
0173 
0174     // move-construct an optional<T> initialized from an rvalue-ref to 'val'.
0175     // Can throw if T::T(T&&) does
0176     optional_base ( init_value_tag, rval_reference_type val )
0177       :
0178       m_initialized(false)
0179     {
0180       construct( optional_detail::move(val) );
0181     }
0182 
0183     // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional<T>.
0184     // Can throw if T::T(T const&) does
0185     optional_base ( bool cond, argument_type val )
0186       :
0187       m_initialized(false)
0188     {
0189       if ( cond )
0190         construct(val);
0191     }
0192 
0193     // Creates an optional<T> initialized with 'move(val)' IFF cond is true, otherwise creates an uninitialized optional<T>.
0194     // Can throw if T::T(T &&) does
0195     optional_base ( bool cond, rval_reference_type val )
0196       :
0197       m_initialized(false)
0198     {
0199       if ( cond )
0200         construct(optional_detail::move(val));
0201     }
0202 
0203     // Creates a deep copy of another optional<T>
0204     // Can throw if T::T(T const&) does
0205     optional_base ( optional_base const& rhs )
0206       :
0207       m_initialized(false)
0208     {
0209       if ( rhs.is_initialized() )
0210         construct(rhs.get_impl());
0211     }
0212 
0213     // Creates a deep move of another optional<T>
0214     // Can throw if T::T(T&&) does
0215     optional_base ( optional_base&& rhs )
0216     BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
0217       :
0218       m_initialized(false)
0219     {
0220       if ( rhs.is_initialized() )
0221         construct( optional_detail::move(rhs.get_impl()) );
0222     }
0223 
0224 
0225     template<class Expr, class PtrExpr>
0226     explicit optional_base ( Expr&& expr, PtrExpr const* tag )
0227       :
0228       m_initialized(false)
0229     {
0230       construct(optional_detail::forward<Expr>(expr),tag);
0231     }
0232 
0233     optional_base& operator= ( optional_base const& rhs )
0234     {
0235       this->assign(rhs);
0236       return *this;
0237     }
0238 
0239     optional_base& operator= ( optional_base && rhs )
0240     BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
0241     {
0242       this->assign(static_cast<optional_base&&>(rhs));
0243       return *this;
0244     }
0245 
0246     // No-throw (assuming T::~T() doesn't)
0247     ~optional_base() { destroy() ; }
0248 
0249     // Assigns from another optional<T> (deep-copies the rhs value)
0250     void assign ( optional_base const& rhs )
0251     {
0252       if (is_initialized())
0253       {
0254         if ( rhs.is_initialized() )
0255              assign_value(rhs.get_impl());
0256         else destroy();
0257       }
0258       else
0259       {
0260         if ( rhs.is_initialized() )
0261           construct(rhs.get_impl());
0262       }
0263     }
0264 
0265     // Assigns from another optional<T> (deep-moves the rhs value)
0266     void assign ( optional_base&& rhs )
0267     {
0268       if (is_initialized())
0269       {
0270         if ( rhs.is_initialized() )
0271              assign_value( optional_detail::move(rhs.get_impl()) );
0272         else destroy();
0273       }
0274       else
0275       {
0276         if ( rhs.is_initialized() )
0277           construct(optional_detail::move(rhs.get_impl()));
0278       }
0279     }
0280 
0281     // Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
0282     template<class U>
0283     void assign ( optional<U> const& rhs )
0284     {
0285       if (is_initialized())
0286       {
0287         if ( rhs.is_initialized() )
0288 #ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
0289           assign_value( rhs.get() );
0290 #else
0291           assign_value( static_cast<value_type>(rhs.get()) );
0292 #endif
0293 
0294         else destroy();
0295       }
0296       else
0297       {
0298         if ( rhs.is_initialized() )
0299 #ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
0300           construct(rhs.get());
0301 #else
0302           construct(static_cast<value_type>(rhs.get()));
0303 #endif
0304       }
0305     }
0306 
0307     // move-assigns from another _convertible_ optional<U> (deep-moves from the rhs value)
0308     template<class U>
0309     void assign ( optional<U>&& rhs )
0310     {
0311       typedef BOOST_DEDUCED_TYPENAME optional<U>::rval_reference_type ref_type;
0312       if (is_initialized())
0313       {
0314         if ( rhs.is_initialized() )
0315              assign_value( static_cast<ref_type>(rhs.get()) );
0316         else destroy();
0317       }
0318       else
0319       {
0320         if ( rhs.is_initialized() )
0321           construct(static_cast<ref_type>(rhs.get()));
0322       }
0323     }
0324 
0325     // Assigns from a T (deep-copies the rhs value)
0326     void assign ( argument_type val )
0327     {
0328       if (is_initialized())
0329            assign_value(val);
0330       else construct(val);
0331     }
0332 
0333     // Assigns from a T (deep-moves the rhs value)
0334     void assign ( rval_reference_type val )
0335     {
0336       if (is_initialized())
0337            assign_value( optional_detail::move(val) );
0338       else construct( optional_detail::move(val) );
0339     }
0340 
0341     // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
0342     // No-throw (assuming T::~T() doesn't)
0343     void assign ( none_t ) BOOST_NOEXCEPT { destroy(); }
0344 
0345 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
0346 
0347     template<class Expr, class ExprPtr>
0348     void assign_expr ( Expr&& expr, ExprPtr const* tag )
0349     {
0350       if (is_initialized())
0351         assign_expr_to_initialized(optional_detail::forward<Expr>(expr),tag);
0352       else construct(optional_detail::forward<Expr>(expr),tag);
0353     }
0354 
0355 #endif
0356 
0357   public :
0358 
0359     // Destroys the current value, if any, leaving this UNINITIALIZED
0360     // No-throw (assuming T::~T() doesn't)
0361     void reset() BOOST_NOEXCEPT { destroy(); }
0362 
0363     // **DEPRECATED** Replaces the current value -if any- with 'val'
0364     void reset ( argument_type val ) { assign(val); }
0365 
0366     // Returns a pointer to the value if this is initialized, otherwise,
0367     // returns NULL.
0368     // No-throw
0369     pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
0370     pointer_type       get_ptr()       { return m_initialized ? get_ptr_impl() : 0 ; }
0371 
0372     bool is_initialized() const BOOST_NOEXCEPT { return m_initialized ; }
0373 
0374   protected :
0375 
0376     void construct ( argument_type val )
0377      {
0378        ::new (m_storage.address()) unqualified_value_type(val) ;
0379        m_initialized = true ;
0380      }
0381 
0382     void construct ( rval_reference_type val )
0383      {
0384        ::new (m_storage.address()) unqualified_value_type( optional_detail::move(val) ) ;
0385        m_initialized = true ;
0386      }
0387 
0388 
0389     // Constructs in-place
0390     // upon exception *this is always uninitialized
0391     template<class... Args>
0392     void construct ( in_place_init_t, Args&&... args )
0393     {
0394       ::new (m_storage.address()) unqualified_value_type( optional_detail::forward<Args>(args)... ) ;
0395       m_initialized = true ;
0396     }
0397 
0398     template<class... Args>
0399     void emplace_assign ( Args&&... args )
0400     {
0401       destroy();
0402       construct(in_place_init, optional_detail::forward<Args>(args)...);
0403     }
0404 
0405     template<class... Args>
0406     explicit optional_base ( in_place_init_t, Args&&... args )
0407       :
0408       m_initialized(false)
0409     {
0410       construct(in_place_init, optional_detail::forward<Args>(args)...);
0411     }
0412 
0413     template<class... Args>
0414     explicit optional_base ( in_place_init_if_t, bool cond, Args&&... args )
0415       :
0416       m_initialized(false)
0417     {
0418       if ( cond )
0419         construct(in_place_init, optional_detail::forward<Args>(args)...);
0420     }
0421 
0422 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
0423 
0424     // Constructs in-place using the given factory
0425     template<class Expr>
0426     void construct ( Expr&& factory, in_place_factory_base const* )
0427      {
0428        boost_optional_detail::construct<value_type>(factory, m_storage.address());
0429        m_initialized = true ;
0430      }
0431 
0432     // Constructs in-place using the given typed factory
0433     template<class Expr>
0434     void construct ( Expr&& factory, typed_in_place_factory_base const* )
0435      {
0436        factory.apply(m_storage.address()) ;
0437        m_initialized = true ;
0438      }
0439 
0440     template<class Expr>
0441     void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag )
0442      {
0443        destroy();
0444        construct(factory,tag);
0445      }
0446 
0447     // Constructs in-place using the given typed factory
0448     template<class Expr>
0449     void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag )
0450      {
0451        destroy();
0452        construct(factory,tag);
0453      }
0454 
0455 #endif
0456 
0457     // Constructs using any expression implicitly convertible to the single argument
0458     // of a one-argument T constructor.
0459     // Converting constructions of optional<T> from optional<U> uses this function with
0460     // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
0461     template<class Expr>
0462     void construct ( Expr&& expr, void const* )
0463     {
0464       new (m_storage.address()) unqualified_value_type(optional_detail::forward<Expr>(expr)) ;
0465       m_initialized = true ;
0466     }
0467 
0468     // Assigns using a form any expression implicitly convertible to the single argument
0469     // of a T's assignment operator.
0470     // Converting assignments of optional<T> from optional<U> uses this function with
0471     // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
0472     template<class Expr>
0473     void assign_expr_to_initialized ( Expr&& expr, void const* )
0474     {
0475       assign_value( optional_detail::forward<Expr>(expr) );
0476     }
0477 
0478 #ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
0479     // BCB5.64 (and probably lower versions) workaround.
0480     //   The in-place factories are supported by means of catch-all constructors
0481     //   and assignment operators (the functions are parameterized in terms of
0482     //   an arbitrary 'Expr' type)
0483     //   This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U>
0484     //   to the 'Expr'-taking functions even though explicit overloads are present for them.
0485     //   Thus, the following overload is needed to properly handle the case when the 'lhs'
0486     //   is another optional.
0487     //
0488     // For VC<=70 compilers this workaround doesn't work because the compiler issues and error
0489     // instead of choosing the wrong overload
0490     //
0491 
0492     // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
0493     template<class Expr>
0494     void construct ( Expr&& expr, optional_tag const* )
0495      {
0496        if ( expr.is_initialized() )
0497        {
0498          // An exception can be thrown here.
0499          // It it happens, THIS will be left uninitialized.
0500          new (m_storage.address()) unqualified_value_type(optional_detail::move(expr.get())) ;
0501          m_initialized = true ;
0502        }
0503      }
0504 #endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
0505 
0506     void assign_value ( argument_type val ) { get_impl() = val; }
0507     void assign_value ( rval_reference_type val ) { get_impl() = static_cast<rval_reference_type>(val); }
0508 
0509     void destroy()
0510     {
0511       if ( m_initialized )
0512         destroy_impl() ;
0513     }
0514 
0515     reference_const_type get_impl() const { return m_storage.ref() ; }
0516     reference_type       get_impl()       { return m_storage.ref() ; }
0517 
0518     pointer_const_type get_ptr_impl() const { return m_storage.ptr_ref(); }
0519     pointer_type       get_ptr_impl()       { return m_storage.ptr_ref(); }
0520 
0521   private :
0522 
0523 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1900))
0524     void destroy_impl ( ) { m_storage.ptr_ref()->~T() ; m_initialized = false ; }
0525 #else
0526     void destroy_impl ( ) { m_storage.ref().T::~T() ; m_initialized = false ; }
0527 #endif
0528 
0529     bool m_initialized ;
0530     storage_type m_storage ;
0531 } ;
0532 
0533 #include <boost/optional/detail/optional_trivially_copyable_base.hpp>
0534 
0535 // definition of metafunction is_optional_val_init_candidate
0536 template <typename U>
0537 struct is_optional_or_tag
0538   : boost::conditional< boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
0539                      || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, none_t>::value
0540                      || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, in_place_init_t>::value
0541                      || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, in_place_init_if_t>::value,
0542     boost::true_type, boost::false_type>::type
0543 {};
0544 
0545 template <typename T, typename U>
0546 struct has_dedicated_constructor
0547   : boost::disjunction<is_optional_or_tag<U>, boost::is_same<T, BOOST_DEDUCED_TYPENAME boost::decay<U>::type> >
0548 {};
0549 
0550 template <typename U>
0551 struct is_in_place_factory
0552   : boost::disjunction< boost::is_base_of<boost::in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>,
0553                         boost::is_base_of<boost::typed_in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type> >
0554 {};
0555 
0556 #if !defined(BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT)
0557 
0558 template <typename T, typename U>
0559 struct is_factory_or_constructible_to_T
0560   : boost::disjunction< is_in_place_factory<U>, boost::is_constructible<T, U&&> >
0561 {};
0562 
0563 template <typename T, typename U>
0564 struct is_optional_constructible : boost::is_constructible<T, U>
0565 {};
0566 
0567 #else
0568 
0569 template <typename, typename>
0570 struct is_factory_or_constructible_to_T : boost::true_type
0571 {};
0572 
0573 template <typename T, typename U>
0574 struct is_optional_constructible : boost::true_type
0575 {};
0576 
0577 #endif // is_convertible condition
0578 
0579 #if !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800)
0580 // for is_assignable
0581 
0582 // On some initial rvalue reference implementations GCC does it in a strange way,
0583 // preferring perfect-forwarding constructor to implicit copy constructor.
0584 
0585 template <typename T, typename U>
0586 struct is_opt_assignable
0587   : boost::conjunction<boost::is_convertible<U&&, T>, boost::is_assignable<T&, U&&> >
0588 {};
0589 
0590 #else
0591 
0592 template <typename T, typename U>
0593 struct is_opt_assignable : boost::is_convertible<U, T>
0594 {};
0595 
0596 #endif
0597 
0598 template <typename T, typename U>
0599 struct is_factory_or_opt_assignable_to_T
0600   : boost::disjunction< is_in_place_factory<U>, is_opt_assignable<T, U> >
0601 {};
0602 
0603 template <typename T, typename U, bool = has_dedicated_constructor<T, U>::value>
0604 struct is_optional_val_init_candidate
0605   : boost::false_type
0606 {};
0607 
0608 template <typename T, typename U>
0609 struct is_optional_val_init_candidate<T, U, false>
0610   : is_factory_or_constructible_to_T<T, U>
0611 {};
0612 
0613 template <typename T, typename U, bool = has_dedicated_constructor<T, U>::value>
0614 struct is_optional_val_assign_candidate
0615   : boost::false_type
0616 {};
0617 
0618 template <typename T, typename U>
0619 struct is_optional_val_assign_candidate<T, U, false>
0620   : is_factory_or_opt_assignable_to_T<T, U>
0621 {};
0622 
0623 } // namespace optional_detail
0624 
0625 namespace optional_config {
0626 
0627 template <typename T>
0628 struct optional_uses_direct_storage_for
0629   : boost::conditional<(boost::is_scalar<T>::value && !boost::is_const<T>::value && !boost::is_volatile<T>::value)
0630                       , boost::true_type, boost::false_type>::type
0631 {};
0632 
0633 } // namespace optional_config
0634 
0635 
0636 #ifndef BOOST_OPTIONAL_DETAIL_NO_DIRECT_STORAGE_SPEC
0637 #  define BOOST_OPTIONAL_BASE_TYPE(T) boost::conditional< optional_config::optional_uses_direct_storage_for<T>::value, \
0638                                       optional_detail::tc_optional_base<T>, \
0639                                       optional_detail::optional_base<T> \
0640                                       >::type
0641 #else
0642 #  define BOOST_OPTIONAL_BASE_TYPE(T) optional_detail::optional_base<T>
0643 #endif
0644 
0645 template<class T>
0646 class optional
0647   : public BOOST_OPTIONAL_BASE_TYPE(T)
0648 {
0649     typedef typename BOOST_OPTIONAL_BASE_TYPE(T) base ;
0650 
0651   public :
0652 
0653     typedef optional<T> this_type ;
0654 
0655     typedef BOOST_DEDUCED_TYPENAME base::value_type           value_type ;
0656     typedef BOOST_DEDUCED_TYPENAME base::reference_type       reference_type ;
0657     typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
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     typedef BOOST_DEDUCED_TYPENAME base::pointer_type         pointer_type ;
0661     typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type   pointer_const_type ;
0662     typedef BOOST_DEDUCED_TYPENAME base::argument_type        argument_type ;
0663 
0664     // Creates an optional<T> uninitialized.
0665     // No-throw
0666     optional() BOOST_NOEXCEPT : base() {}
0667 
0668     // Creates an optional<T> uninitialized.
0669     // No-throw
0670     optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {}
0671 
0672     // Creates an optional<T> initialized with 'val'.
0673     // Can throw if T::T(T const&) does
0674     optional ( argument_type val ) : base(optional_detail::init_value_tag(), val) {}
0675 
0676     // Creates an optional<T> initialized with 'move(val)'.
0677     // Can throw if T::T(T &&) does
0678     optional ( rval_reference_type val ) : base(optional_detail::init_value_tag(), optional_detail::forward<T>(val))
0679       {}
0680 
0681     // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
0682     // Can throw if T::T(T const&) does
0683     optional ( bool cond, argument_type val ) : base(cond,val) {}
0684 
0685     /// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
0686     // Can throw if T::T(T &&) does
0687     optional ( bool cond, rval_reference_type val ) : base( cond, optional_detail::forward<T>(val) )
0688       {}
0689 
0690     // NOTE: MSVC needs templated versions first
0691 
0692     // Creates a deep copy of another convertible optional<U>
0693     // Requires a valid conversion from U to T.
0694     // Can throw if T::T(U const&) does
0695     template<class U>
0696     explicit optional ( optional<U> const& rhs
0697 #ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS
0698                         ,BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_constructible<T, U const&>, bool>::type = true
0699 #endif
0700                       )
0701       :
0702       base()
0703     {
0704       if ( rhs.is_initialized() )
0705         this->construct(rhs.get());
0706     }
0707 
0708     // Creates a deep move of another convertible optional<U>
0709     // Requires a valid conversion from U to T.
0710     // Can throw if T::T(U&&) does
0711     template<class U>
0712     explicit optional ( optional<U> && rhs
0713 #ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS
0714                         ,BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_constructible<T, U>, bool>::type = true
0715 #endif
0716                       )
0717       :
0718       base()
0719     {
0720       if ( rhs.is_initialized() )
0721         this->construct( optional_detail::move(rhs.get()) );
0722     }
0723 
0724 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
0725     // Creates an optional<T> with an expression which can be either
0726     //  (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
0727     //  (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
0728     //  (c) Any expression implicitly convertible to the single type
0729     //      of a one-argument T's constructor.
0730     //  (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
0731     //       even though explicit overloads are present for these.
0732     // Depending on the above some T ctor is called.
0733     // Can throw if the resolved T ctor throws.
0734 
0735 
0736   template<class Expr>
0737   explicit optional ( Expr&& expr,
0738                       BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_val_init_candidate<T, Expr>, bool>::type = true
0739   )
0740     : base(optional_detail::forward<Expr>(expr),boost::addressof(expr))
0741     {}
0742 
0743 #endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
0744 
0745     // Creates a deep copy of another optional<T>
0746     // Can throw if T::T(T const&) does
0747 #ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
0748     optional ( optional const& ) = default;
0749 #else
0750     optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
0751 #endif
0752 
0753     // Creates a deep move of another optional<T>
0754     // Can throw if T::T(T&&) does
0755 #ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
0756     optional ( optional && ) = default;
0757 #else
0758     optional ( optional && rhs )
0759       BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
0760       : base( optional_detail::move(rhs) )
0761     {}
0762 #endif
0763 
0764 
0765 #if BOOST_WORKAROUND(_MSC_VER, <= 1600)
0766     //  On old MSVC compilers the implicitly declared dtor is not called
0767     ~optional() {}
0768 #endif
0769 
0770 
0771 #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
0772     // Assigns from an expression. See corresponding constructor.
0773     // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
0774 
0775     template<class Expr>
0776     BOOST_DEDUCED_TYPENAME boost::enable_if<optional_detail::is_optional_val_assign_candidate<T, Expr>, optional&>::type
0777     operator= ( Expr&& expr )
0778       {
0779         this->assign_expr(optional_detail::forward<Expr>(expr),boost::addressof(expr));
0780         return *this ;
0781       }
0782 
0783 #endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
0784 
0785     // Copy-assigns from another convertible optional<U> (converts && deep-copies the rhs value)
0786     // Requires a valid conversion from U to T.
0787     // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
0788     template<class U>
0789     optional& operator= ( optional<U> const& rhs )
0790       {
0791         this->assign(rhs);
0792         return *this ;
0793       }
0794 
0795     // Move-assigns from another convertible optional<U> (converts && deep-moves the rhs value)
0796     // Requires a valid conversion from U to T.
0797     // Basic Guarantee: If T::T( U && ) throws, this is left UNINITIALIZED
0798     template<class U>
0799     optional& operator= ( optional<U> && rhs )
0800       {
0801         this->assign(optional_detail::move(rhs));
0802         return *this ;
0803       }
0804 
0805     // Assigns from another optional<T> (deep-copies the rhs value)
0806     // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
0807     //  (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
0808 #ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
0809     optional& operator= ( optional const& rhs ) = default;
0810 #else
0811     optional& operator= ( optional const& rhs )
0812       {
0813         this->assign( static_cast<base const&>(rhs) ) ;
0814         return *this ;
0815       }
0816 #endif
0817 
0818     // Assigns from another optional<T> (deep-moves the rhs value)
0819 #ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
0820     optional& operator= ( optional && ) = default;
0821 #else
0822     optional& operator= ( optional && rhs )
0823       BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
0824       {
0825         this->assign( static_cast<base &&>(rhs) ) ;
0826         return *this ;
0827       }
0828 #endif
0829 
0830 #ifndef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
0831 
0832     // Assigns from a T (deep-moves/copies the rhs value)
0833     template <typename T_>
0834     BOOST_DEDUCED_TYPENAME boost::enable_if<boost::is_same<T, BOOST_DEDUCED_TYPENAME boost::decay<T_>::type>, optional&>::type
0835     operator= ( T_&& val )
0836       {
0837         this->assign( optional_detail::forward<T_>(val) ) ;
0838         return *this ;
0839       }
0840 
0841 #else
0842 
0843     // Assigns from a T (deep-copies the rhs value)
0844     // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
0845     optional& operator= ( argument_type val )
0846       {
0847         this->assign( val ) ;
0848         return *this ;
0849       }
0850 
0851     // Assigns from a T (deep-moves the rhs value)
0852     optional& operator= ( rval_reference_type val )
0853       {
0854         this->assign( optional_detail::move(val) ) ;
0855         return *this ;
0856       }
0857 
0858 #endif // BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
0859 
0860     // Assigns from a "none"
0861     // Which destroys the current value, if any, leaving this UNINITIALIZED
0862     // No-throw (assuming T::~T() doesn't)
0863     optional& operator= ( none_t none_ ) BOOST_NOEXCEPT
0864       {
0865         this->assign( none_ ) ;
0866         return *this ;
0867       }
0868 
0869     // Constructs in-place
0870     // upon exception *this is always uninitialized
0871     template<class... Args>
0872     void emplace ( Args&&... args )
0873     {
0874       this->emplace_assign( optional_detail::forward<Args>(args)... );
0875     }
0876 
0877     template<class... Args>
0878     explicit optional ( in_place_init_t, Args&&... args )
0879     : base( in_place_init, optional_detail::forward<Args>(args)... )
0880     {}
0881 
0882     template<class... Args>
0883     explicit optional ( in_place_init_if_t, bool cond, Args&&... args )
0884     : base( in_place_init_if, cond, optional_detail::forward<Args>(args)... )
0885     {}
0886 
0887     void swap( optional & arg )
0888       BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
0889       {
0890         // allow for Koenig lookup
0891         boost::core::invoke_swap(*this, arg);
0892       }
0893 
0894 
0895     // Returns a reference to the value if this is initialized, otherwise,
0896     // the behaviour is UNDEFINED
0897     // No-throw
0898     reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
0899     reference_type       get()       { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
0900 
0901     // Returns a copy of the value if this is initialized, 'v' otherwise
0902     reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
0903     reference_type       get_value_or ( reference_type       v )       { return this->is_initialized() ? get() : v ; }
0904 
0905     // Returns a pointer to the value if this is initialized, otherwise,
0906     // the behaviour is UNDEFINED
0907     // No-throw
0908     pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
0909     pointer_type       operator->()       { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
0910 
0911     // Returns a reference to the value if this is initialized, otherwise,
0912     // the behaviour is UNDEFINED
0913     // No-throw
0914     reference_const_type operator *() BOOST_OPTIONAL_CONST_REF_QUAL { return this->get() ; }
0915     reference_type       operator *() BOOST_OPTIONAL_REF_QUAL       { return this->get() ; }
0916 
0917 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
0918     reference_type_of_temporary_wrapper operator *() && { return optional_detail::move(this->get()) ; }
0919 #endif
0920 
0921     reference_const_type value() BOOST_OPTIONAL_CONST_REF_QUAL
0922       {
0923         if (this->is_initialized())
0924           return this->get() ;
0925         else
0926           throw_exception(bad_optional_access());
0927       }
0928 
0929     reference_type value() BOOST_OPTIONAL_REF_QUAL
0930       {
0931         if (this->is_initialized())
0932           return this->get() ;
0933         else
0934           throw_exception(bad_optional_access());
0935       }
0936 
0937     template <class U>
0938     value_type value_or ( U&& v ) BOOST_OPTIONAL_CONST_REF_QUAL
0939       {
0940         if (this->is_initialized())
0941           return get();
0942         else
0943           return optional_detail::forward<U>(v);
0944       }
0945 
0946     template <typename F>
0947     value_type value_or_eval ( F f ) BOOST_OPTIONAL_CONST_REF_QUAL
0948       {
0949         if (this->is_initialized())
0950           return get();
0951         else
0952           return f();
0953       }
0954 
0955 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
0956     reference_type_of_temporary_wrapper value() &&
0957       {
0958         if (this->is_initialized())
0959           return optional_detail::move(this->get()) ;
0960         else
0961           throw_exception(bad_optional_access());
0962       }
0963 
0964     template <class U>
0965     value_type value_or ( U&& v ) &&
0966       {
0967         if (this->is_initialized())
0968           return optional_detail::move(get());
0969         else
0970           return optional_detail::forward<U>(v);
0971       }
0972 
0973     template <typename F>
0974     value_type value_or_eval ( F f ) &&
0975       {
0976         if (this->is_initialized())
0977           return optional_detail::move(get());
0978         else
0979           return f();
0980       }
0981 #endif
0982 
0983 // Monadic interface
0984 
0985     template <typename F>
0986     optional<typename optional_detail::result_of<F, reference_type>::type> map(F f) BOOST_OPTIONAL_REF_QUAL
0987       {
0988         if (this->has_value())
0989           return f(get());
0990         else
0991           return none;
0992       }
0993 
0994     template <typename F>
0995     optional<typename optional_detail::result_of<F, reference_const_type>::type> map(F f) BOOST_OPTIONAL_CONST_REF_QUAL
0996       {
0997         if (this->has_value())
0998           return f(get());
0999         else
1000           return none;
1001       }
1002 
1003 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
1004     template <typename F>
1005     optional<typename optional_detail::result_of<F, reference_type_of_temporary_wrapper>::type> map(F f) &&
1006       {
1007         if (this->has_value())
1008           return f(optional_detail::move(this->get()));
1009         else
1010           return none;
1011       }
1012 #endif
1013 
1014     template <typename F>
1015     optional<typename optional_detail::result_value_type<F, reference_type>::type>
1016     flat_map(F f) BOOST_OPTIONAL_REF_QUAL
1017       {
1018         if (this->has_value())
1019           return f(get());
1020         else
1021           return none;
1022       }
1023 
1024     template <typename F>
1025     optional<typename optional_detail::result_value_type<F, reference_const_type>::type>
1026     flat_map(F f) BOOST_OPTIONAL_CONST_REF_QUAL
1027       {
1028         if (this->has_value())
1029           return f(get());
1030         else
1031           return none;
1032       }
1033 
1034 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
1035     template <typename F>
1036     optional<typename optional_detail::result_value_type<F, reference_type_of_temporary_wrapper>::type>
1037     flat_map(F f) &&
1038       {
1039         if (this->has_value())
1040           return f(optional_detail::move(get()));
1041         else
1042           return none;
1043       }
1044 #endif
1045 
1046     bool has_value() const BOOST_NOEXCEPT { return this->is_initialized() ; }
1047 
1048     explicit operator bool() const BOOST_NOEXCEPT { return this->has_value() ; }
1049 } ;
1050 
1051 
1052 template<class T>
1053 class optional<T&&>
1054 {
1055   static_assert(sizeof(T) == 0, "Optional rvalue references are illegal.");
1056 } ;
1057 
1058 } // namespace boost
1059 
1060 #ifndef BOOST_OPTIONAL_CONFIG_DONT_SPECIALIZE_OPTIONAL_REFS
1061 # include <boost/optional/detail/optional_reference_spec.hpp>
1062 #endif
1063 
1064 namespace boost {
1065 
1066 
1067 template<class T>
1068 inline
1069 optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type> make_optional ( T && v  )
1070 {
1071   return optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type>(optional_detail::forward<T>(v));
1072 }
1073 
1074 // Returns optional<T>(cond,v)
1075 template<class T>
1076 inline
1077 optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type> make_optional ( bool cond, T && v )
1078 {
1079   return optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type>(cond,optional_detail::forward<T>(v));
1080 }
1081 
1082 
1083 // Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
1084 // No-throw
1085 template<class T>
1086 inline
1087 BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
1088 get ( optional<T> const& opt )
1089 {
1090   return opt.get() ;
1091 }
1092 
1093 template<class T>
1094 inline
1095 BOOST_DEDUCED_TYPENAME optional<T>::reference_type
1096 get ( optional<T>& opt )
1097 {
1098   return opt.get() ;
1099 }
1100 
1101 // Returns a pointer to the value if this is initialized, otherwise, returns NULL.
1102 // No-throw
1103 template<class T>
1104 inline
1105 BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
1106 get ( optional<T> const* opt )
1107 {
1108   return opt->get_ptr() ;
1109 }
1110 
1111 template<class T>
1112 inline
1113 BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
1114 get ( optional<T>* opt )
1115 {
1116   return opt->get_ptr() ;
1117 }
1118 
1119 // Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
1120 // No-throw
1121 template<class T>
1122 inline
1123 BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
1124 get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v )
1125 {
1126   return opt.get_value_or(v) ;
1127 }
1128 
1129 template<class T>
1130 inline
1131 BOOST_DEDUCED_TYPENAME optional<T>::reference_type
1132 get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v )
1133 {
1134   return opt.get_value_or(v) ;
1135 }
1136 
1137 // Returns a pointer to the value if this is initialized, otherwise, returns NULL.
1138 // No-throw
1139 template<class T>
1140 inline
1141 BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
1142 get_pointer ( optional<T> const& opt )
1143 {
1144   return opt.get_ptr() ;
1145 }
1146 
1147 template<class T>
1148 inline
1149 BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
1150 get_pointer ( optional<T>& opt )
1151 {
1152   return opt.get_ptr() ;
1153 }
1154 
1155 } // namespace boost
1156 
1157 #ifndef BOOST_NO_IOSTREAM
1158 namespace boost {
1159 
1160 // The following declaration prevents a bug where operator safe-bool is used upon streaming optional object if you forget the IO header.
1161 template<class CharType, class CharTrait>
1162 std::basic_ostream<CharType, CharTrait>&
1163 operator<<(std::basic_ostream<CharType, CharTrait>& os, optional_detail::optional_tag const&)
1164 {
1165   static_assert(sizeof(CharType) == 0, "If you want to output boost::optional, include header <boost/optional/optional_io.hpp>");
1166   return os;
1167 }
1168 
1169 } // namespace boost
1170 #endif // BOOST_NO_IOSTREAM
1171 
1172 #include <boost/optional/detail/optional_relops.hpp>
1173 #include <boost/optional/detail/optional_swap.hpp>
1174 
1175 #endif // header guard