1 // Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
2 // Copyright (C) 2014 - 2017 Andrzej Krzemienski.
4 // Use, modification, and distribution is subject to the Boost Software
5 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
8 // See http://www.boost.org/libs/optional for documentation.
10 // You are welcome to contact the author at:
11 // fernando_cacciola@hotmail.com
14 // 27 Apr 2008 (improved swap) Fernando Cacciola, Niels Dekker, Thorsten Ottosen
15 // 05 May 2014 (Added move semantics) Andrzej Krzemienski
17 #ifndef BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
18 #define BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
23 #ifdef BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS
24 # include <type_traits>
27 #include <boost/assert.hpp>
28 #include <boost/core/addressof.hpp>
29 #include <boost/core/enable_if.hpp>
30 #include <boost/core/explicit_operator_bool.hpp>
31 #include <boost/core/swap.hpp>
32 #include <boost/optional/bad_optional_access.hpp>
33 #include <boost/static_assert.hpp>
34 #include <boost/throw_exception.hpp>
35 #include <boost/type.hpp>
36 #include <boost/type_traits/alignment_of.hpp>
37 #include <boost/type_traits/conditional.hpp>
38 #include <boost/type_traits/has_nothrow_constructor.hpp>
39 #include <boost/type_traits/type_with_alignment.hpp>
40 #include <boost/type_traits/remove_const.hpp>
41 #include <boost/type_traits/remove_reference.hpp>
42 #include <boost/type_traits/decay.hpp>
43 #include <boost/type_traits/is_base_of.hpp>
44 #include <boost/type_traits/is_const.hpp>
45 #include <boost/type_traits/is_constructible.hpp>
46 #include <boost/type_traits/is_lvalue_reference.hpp>
47 #include <boost/type_traits/is_nothrow_move_assignable.hpp>
48 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
49 #include <boost/type_traits/is_rvalue_reference.hpp>
50 #include <boost/type_traits/is_same.hpp>
51 #include <boost/type_traits/is_volatile.hpp>
52 #include <boost/type_traits/is_scalar.hpp>
53 #include <boost/move/utility.hpp>
54 #include <boost/none.hpp>
55 #include <boost/utility/compare_pointees.hpp>
57 #include <boost/optional/optional_fwd.hpp>
58 #include <boost/optional/detail/optional_config.hpp>
59 #include <boost/optional/detail/optional_factory_support.hpp>
60 #include <boost/optional/detail/optional_aligned_storage.hpp>
62 #ifdef BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL
63 #include <boost/optional/detail/old_optional_implementation.hpp>
67 namespace optional_ns {
69 // a tag for in-place initialization of contained value
70 struct in_place_init_t
73 explicit in_place_init_t(init_tag){}
75 const in_place_init_t in_place_init ((in_place_init_t::init_tag()));
77 // a tag for conditional in-place initialization of contained value
78 struct in_place_init_if_t
81 explicit in_place_init_if_t(init_tag){}
83 const in_place_init_if_t in_place_init_if ((in_place_init_if_t::init_tag()));
85 } // namespace optional_ns
87 using optional_ns::in_place_init_t;
88 using optional_ns::in_place_init;
89 using optional_ns::in_place_init_if_t;
90 using optional_ns::in_place_init_if;
92 namespace optional_detail {
94 struct optional_tag {} ;
98 class optional_base : public optional_tag
102 typedef aligned_storage<T> storage_type ;
103 typedef optional_base<T> this_type ;
107 typedef T value_type ;
110 typedef T & reference_type ;
111 typedef T const& reference_const_type ;
112 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
113 typedef T && rval_reference_type ;
114 typedef T && reference_type_of_temporary_wrapper ;
116 typedef T * pointer_type ;
117 typedef T const* pointer_const_type ;
118 typedef T const& argument_type ;
120 // Creates an optional<T> uninitialized.
124 m_initialized(false) {}
126 // Creates an optional<T> uninitialized.
128 optional_base ( none_t )
130 m_initialized(false) {}
132 // Creates an optional<T> initialized with 'val'.
133 // Can throw if T::T(T const&) does
134 optional_base ( argument_type val )
141 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
142 // move-construct an optional<T> initialized from an rvalue-ref to 'val'.
143 // Can throw if T::T(T&&) does
144 optional_base ( rval_reference_type val )
148 construct( boost::move(val) );
152 // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>.
153 // Can throw if T::T(T const&) does
154 optional_base ( bool cond, argument_type val )
162 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
163 // Creates an optional<T> initialized with 'move(val)' IFF cond is true, otherwise creates an uninitialzed optional<T>.
164 // Can throw if T::T(T &&) does
165 optional_base ( bool cond, rval_reference_type val )
170 construct(boost::move(val));
174 // Creates a deep copy of another optional<T>
175 // Can throw if T::T(T const&) does
176 optional_base ( optional_base const& rhs )
180 if ( rhs.is_initialized() )
181 construct(rhs.get_impl());
184 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
185 // Creates a deep move of another optional<T>
186 // Can throw if T::T(T&&) does
187 optional_base ( optional_base&& rhs )
188 BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
192 if ( rhs.is_initialized() )
193 construct( boost::move(rhs.get_impl()) );
197 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
199 template<class Expr, class PtrExpr>
200 explicit optional_base ( Expr&& expr, PtrExpr const* tag )
204 construct(boost::forward<Expr>(expr),tag);
208 // This is used for both converting and in-place constructions.
209 // Derived classes use the 'tag' to select the appropriate
210 // implementation (the correct 'construct()' overload)
212 explicit optional_base ( Expr const& expr, Expr const* tag )
221 optional_base& operator= ( optional_base const& rhs )
227 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
228 optional_base& operator= ( optional_base && rhs )
229 BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
231 this->assign(static_cast<optional_base&&>(rhs));
236 // No-throw (assuming T::~T() doesn't)
237 ~optional_base() { destroy() ; }
239 // Assigns from another optional<T> (deep-copies the rhs value)
240 void assign ( optional_base const& rhs )
242 if (is_initialized())
244 if ( rhs.is_initialized() )
245 assign_value(rhs.get_impl());
250 if ( rhs.is_initialized() )
251 construct(rhs.get_impl());
255 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
256 // Assigns from another optional<T> (deep-moves the rhs value)
257 void assign ( optional_base&& rhs )
259 if (is_initialized())
261 if ( rhs.is_initialized() )
262 assign_value( boost::move(rhs.get_impl()) );
267 if ( rhs.is_initialized() )
268 construct(boost::move(rhs.get_impl()));
273 // Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
275 void assign ( optional<U> const& rhs )
277 if (is_initialized())
279 if ( rhs.is_initialized() )
280 #ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
281 assign_value( rhs.get() );
283 assign_value( static_cast<value_type>(rhs.get()) );
290 if ( rhs.is_initialized() )
291 #ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
292 construct(rhs.get());
294 construct(static_cast<value_type>(rhs.get()));
299 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
300 // move-assigns from another _convertible_ optional<U> (deep-moves from the rhs value)
302 void assign ( optional<U>&& rhs )
304 typedef BOOST_DEDUCED_TYPENAME optional<U>::rval_reference_type ref_type;
305 if (is_initialized())
307 if ( rhs.is_initialized() )
308 assign_value( static_cast<ref_type>(rhs.get()) );
313 if ( rhs.is_initialized() )
314 construct(static_cast<ref_type>(rhs.get()));
319 // Assigns from a T (deep-copies the rhs value)
320 void assign ( argument_type val )
322 if (is_initialized())
327 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
328 // Assigns from a T (deep-moves the rhs value)
329 void assign ( rval_reference_type val )
331 if (is_initialized())
332 assign_value( boost::move(val) );
333 else construct( boost::move(val) );
337 // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
338 // No-throw (assuming T::~T() doesn't)
339 void assign ( none_t ) BOOST_NOEXCEPT { destroy(); }
341 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
343 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
344 template<class Expr, class ExprPtr>
345 void assign_expr ( Expr&& expr, ExprPtr const* tag )
347 if (is_initialized())
348 assign_expr_to_initialized(boost::forward<Expr>(expr),tag);
349 else construct(boost::forward<Expr>(expr),tag);
353 void assign_expr ( Expr const& expr, Expr const* tag )
355 if (is_initialized())
356 assign_expr_to_initialized(expr,tag);
357 else construct(expr,tag);
365 // **DEPPRECATED** Destroys the current value, if any, leaving this UNINITIALIZED
366 // No-throw (assuming T::~T() doesn't)
367 void reset() BOOST_NOEXCEPT { destroy(); }
369 // **DEPPRECATED** Replaces the current value -if any- with 'val'
370 void reset ( argument_type val ) { assign(val); }
372 // Returns a pointer to the value if this is initialized, otherwise,
375 pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
376 pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; }
378 bool is_initialized() const { return m_initialized ; }
382 void construct ( argument_type val )
384 ::new (m_storage.address()) value_type(val) ;
385 m_initialized = true ;
388 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
389 void construct ( rval_reference_type val )
391 ::new (m_storage.address()) value_type( boost::move(val) ) ;
392 m_initialized = true ;
397 #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
398 // Constructs in-place
399 // upon exception *this is always uninitialized
400 template<class... Args>
401 void construct ( in_place_init_t, Args&&... args )
403 ::new (m_storage.address()) value_type( boost::forward<Args>(args)... ) ;
404 m_initialized = true ;
407 template<class... Args>
408 void emplace_assign ( Args&&... args )
411 construct(in_place_init, boost::forward<Args>(args)...);
414 template<class... Args>
415 explicit optional_base ( in_place_init_t, Args&&... args )
419 construct(in_place_init, boost::forward<Args>(args)...);
422 template<class... Args>
423 explicit optional_base ( in_place_init_if_t, bool cond, Args&&... args )
428 construct(in_place_init, boost::forward<Args>(args)...);
430 #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
432 void construct ( in_place_init_t, Arg&& arg )
434 ::new (m_storage.address()) value_type( boost::forward<Arg>(arg) );
435 m_initialized = true ;
438 void construct ( in_place_init_t )
440 ::new (m_storage.address()) value_type();
441 m_initialized = true ;
445 void emplace_assign ( Arg&& arg )
448 construct(in_place_init, boost::forward<Arg>(arg)) ;
451 void emplace_assign ()
454 construct(in_place_init) ;
458 explicit optional_base ( in_place_init_t, Arg&& arg )
462 construct(in_place_init, boost::forward<Arg>(arg));
465 explicit optional_base ( in_place_init_t )
469 construct(in_place_init);
473 explicit optional_base ( in_place_init_if_t, bool cond, Arg&& arg )
478 construct(in_place_init, boost::forward<Arg>(arg));
481 explicit optional_base ( in_place_init_if_t, bool cond )
486 construct(in_place_init);
492 void construct ( in_place_init_t, const Arg& arg )
494 ::new (m_storage.address()) value_type( arg );
495 m_initialized = true ;
499 void construct ( in_place_init_t, Arg& arg )
501 ::new (m_storage.address()) value_type( arg );
502 m_initialized = true ;
505 void construct ( in_place_init_t )
507 ::new (m_storage.address()) value_type();
508 m_initialized = true ;
512 void emplace_assign ( const Arg& arg )
515 construct(in_place_init, arg);
519 void emplace_assign ( Arg& arg )
522 construct(in_place_init, arg);
525 void emplace_assign ()
528 construct(in_place_init);
532 explicit optional_base ( in_place_init_t, const Arg& arg )
533 : m_initialized(false)
535 construct(in_place_init, arg);
539 explicit optional_base ( in_place_init_t, Arg& arg )
540 : m_initialized(false)
542 construct(in_place_init, arg);
545 explicit optional_base ( in_place_init_t )
546 : m_initialized(false)
548 construct(in_place_init);
552 explicit optional_base ( in_place_init_if_t, bool cond, const Arg& arg )
553 : m_initialized(false)
556 construct(in_place_init, arg);
560 explicit optional_base ( in_place_init_if_t, bool cond, Arg& arg )
561 : m_initialized(false)
564 construct(in_place_init, arg);
567 explicit optional_base ( in_place_init_if_t, bool cond )
568 : m_initialized(false)
571 construct(in_place_init);
575 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
577 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
578 // Constructs in-place using the given factory
580 void construct ( Expr&& factory, in_place_factory_base const* )
582 boost_optional_detail::construct<value_type>(factory, m_storage.address());
583 m_initialized = true ;
586 // Constructs in-place using the given typed factory
588 void construct ( Expr&& factory, typed_in_place_factory_base const* )
590 factory.apply(m_storage.address()) ;
591 m_initialized = true ;
595 void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag )
598 construct(factory,tag);
601 // Constructs in-place using the given typed factory
603 void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag )
606 construct(factory,tag);
610 // Constructs in-place using the given factory
612 void construct ( Expr const& factory, in_place_factory_base const* )
614 boost_optional_detail::construct<value_type>(factory, m_storage.address());
615 m_initialized = true ;
618 // Constructs in-place using the given typed factory
620 void construct ( Expr const& factory, typed_in_place_factory_base const* )
622 factory.apply(m_storage.address()) ;
623 m_initialized = true ;
627 void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag )
630 construct(factory,tag);
633 // Constructs in-place using the given typed factory
635 void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag )
638 construct(factory,tag);
644 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
645 // Constructs using any expression implicitly convertible to the single argument
646 // of a one-argument T constructor.
647 // Converting constructions of optional<T> from optional<U> uses this function with
648 // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
650 void construct ( Expr&& expr, void const* )
652 new (m_storage.address()) value_type(boost::forward<Expr>(expr)) ;
653 m_initialized = true ;
656 // Assigns using a form any expression implicitly convertible to the single argument
657 // of a T's assignment operator.
658 // Converting assignments of optional<T> from optional<U> uses this function with
659 // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
661 void assign_expr_to_initialized ( Expr&& expr, void const* )
663 assign_value( boost::forward<Expr>(expr) );
666 // Constructs using any expression implicitly convertible to the single argument
667 // of a one-argument T constructor.
668 // Converting constructions of optional<T> from optional<U> uses this function with
669 // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
671 void construct ( Expr const& expr, void const* )
673 new (m_storage.address()) value_type(expr) ;
674 m_initialized = true ;
677 // Assigns using a form any expression implicitly convertible to the single argument
678 // of a T's assignment operator.
679 // Converting assignments of optional<T> from optional<U> uses this function with
680 // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
682 void assign_expr_to_initialized ( Expr const& expr, void const* )
689 #ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
690 // BCB5.64 (and probably lower versions) workaround.
691 // The in-place factories are supported by means of catch-all constructors
692 // and assignment operators (the functions are parameterized in terms of
693 // an arbitrary 'Expr' type)
694 // This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U>
695 // to the 'Expr'-taking functions even though explicit overloads are present for them.
696 // Thus, the following overload is needed to properly handle the case when the 'lhs'
697 // is another optional.
699 // For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error
700 // instead of choosing the wrong overload
702 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
703 // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
705 void construct ( Expr&& expr, optional_tag const* )
707 if ( expr.is_initialized() )
709 // An exception can be thrown here.
710 // It it happens, THIS will be left uninitialized.
711 new (m_storage.address()) value_type(boost::move(expr.get())) ;
712 m_initialized = true ;
716 // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
718 void construct ( Expr const& expr, optional_tag const* )
720 if ( expr.is_initialized() )
722 // An exception can be thrown here.
723 // It it happens, THIS will be left uninitialized.
724 new (m_storage.address()) value_type(expr.get()) ;
725 m_initialized = true ;
729 #endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
731 void assign_value ( argument_type val ) { get_impl() = val; }
732 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
733 void assign_value ( rval_reference_type val ) { get_impl() = static_cast<rval_reference_type>(val); }
742 reference_const_type get_impl() const { return m_storage.ref() ; }
743 reference_type get_impl() { return m_storage.ref() ; }
745 pointer_const_type get_ptr_impl() const { return m_storage.ptr_ref(); }
746 pointer_type get_ptr_impl() { return m_storage.ptr_ref(); }
750 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1600)
751 void destroy_impl ( ) { m_storage.ptr_ref()->~T() ; m_initialized = false ; }
753 void destroy_impl ( ) { m_storage.ref().T::~T() ; m_initialized = false ; }
757 storage_type m_storage ;
762 #include <boost/optional/detail/optional_trivially_copyable_base.hpp>
764 // definition of metafunciton is_optional_val_init_candidate
765 template <typename U>
766 struct is_optional_related
767 : boost::conditional< boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
768 || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, none_t>::value
769 || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, in_place_init_t>::value
770 || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, in_place_init_if_t>::value,
771 boost::true_type, boost::false_type>::type
774 #if !defined(BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT)
776 template <typename T, typename U>
777 struct is_convertible_to_T_or_factory
778 : boost::conditional< boost::is_base_of<boost::in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
779 || boost::is_base_of<boost::typed_in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
780 || (boost::is_constructible<T, U&&>::value && !boost::is_same<T, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value)
781 , boost::true_type, boost::false_type>::type
784 template <typename T, typename U>
785 struct is_optional_constructible : boost::is_constructible<T, U>
790 template <typename, typename>
791 struct is_convertible_to_T_or_factory : boost::true_type
794 template <typename T, typename U>
795 struct is_optional_constructible : boost::true_type
798 #endif // is_convertible condition
800 template <typename T, typename U>
801 struct is_optional_val_init_candidate
802 : boost::conditional< !is_optional_related<U>::value && is_convertible_to_T_or_factory<T, U>::value
803 , boost::true_type, boost::false_type>::type
806 } // namespace optional_detail
808 namespace optional_config {
810 template <typename T>
811 struct optional_uses_direct_storage_for
812 : boost::conditional<(boost::is_scalar<T>::value && !boost::is_const<T>::value && !boost::is_volatile<T>::value)
813 , boost::true_type, boost::false_type>::type
816 } // namespace optional_config
819 #ifndef BOOST_OPTIONAL_DETAIL_NO_DIRECT_STORAGE_SPEC
820 # define BOOST_OPTIONAL_BASE_TYPE(T) boost::conditional< optional_config::optional_uses_direct_storage_for<T>::value, \
821 optional_detail::tc_optional_base<T>, \
822 optional_detail::optional_base<T> \
825 # define BOOST_OPTIONAL_BASE_TYPE(T) optional_detail::optional_base<T>
830 : public BOOST_OPTIONAL_BASE_TYPE(T)
832 typedef typename BOOST_OPTIONAL_BASE_TYPE(T) base ;
836 typedef optional<T> this_type ;
838 typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ;
839 typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ;
840 typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
841 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
842 typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type rval_reference_type ;
843 typedef BOOST_DEDUCED_TYPENAME base::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ;
845 typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ;
846 typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ;
847 typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
849 // Creates an optional<T> uninitialized.
851 optional() BOOST_NOEXCEPT : base() {}
853 // Creates an optional<T> uninitialized.
855 optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {}
857 // Creates an optional<T> initialized with 'val'.
858 // Can throw if T::T(T const&) does
859 optional ( argument_type val ) : base(val) {}
861 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
862 // Creates an optional<T> initialized with 'move(val)'.
863 // Can throw if T::T(T &&) does
864 optional ( rval_reference_type val ) : base( boost::forward<T>(val) )
868 // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
869 // Can throw if T::T(T const&) does
870 optional ( bool cond, argument_type val ) : base(cond,val) {}
872 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
873 /// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
874 // Can throw if T::T(T &&) does
875 optional ( bool cond, rval_reference_type val ) : base( cond, boost::forward<T>(val) )
879 // NOTE: MSVC needs templated versions first
881 // Creates a deep copy of another convertible optional<U>
882 // Requires a valid conversion from U to T.
883 // Can throw if T::T(U const&) does
885 explicit optional ( optional<U> const& rhs
886 #ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS
887 ,typename boost::enable_if< optional_detail::is_optional_constructible<T, U const&> >::type* = 0
893 if ( rhs.is_initialized() )
894 this->construct(rhs.get());
897 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
898 // Creates a deep move of another convertible optional<U>
899 // Requires a valid conversion from U to T.
900 // Can throw if T::T(U&&) does
902 explicit optional ( optional<U> && rhs
903 #ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS
904 ,typename boost::enable_if< optional_detail::is_optional_constructible<T, U> >::type* = 0
910 if ( rhs.is_initialized() )
911 this->construct( boost::move(rhs.get()) );
915 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
916 // Creates an optional<T> with an expression which can be either
917 // (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
918 // (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
919 // (c) Any expression implicitly convertible to the single type
920 // of a one-argument T's constructor.
921 // (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
922 // even though explicit overloads are present for these.
923 // Depending on the above some T ctor is called.
924 // Can throw if the resolved T ctor throws.
925 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
929 explicit optional ( Expr&& expr,
930 BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_val_init_candidate<T, Expr> >::type* = 0
932 : base(boost::forward<Expr>(expr),boost::addressof(expr))
937 explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
938 #endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
939 #endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
941 // Creates a deep copy of another optional<T>
942 // Can throw if T::T(T const&) does
943 #ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
944 optional ( optional const& ) = default;
946 optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
949 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
950 // Creates a deep move of another optional<T>
951 // Can throw if T::T(T&&) does
953 #ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
954 optional ( optional && rhs ) = default;
956 optional ( optional && rhs )
957 BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
958 : base( boost::move(rhs) )
964 #if BOOST_WORKAROUND(_MSC_VER, <= 1600)
965 // On old MSVC compilers the implicitly declared dtor is not called
970 #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
971 // Assigns from an expression. See corresponding constructor.
972 // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
973 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
976 BOOST_DEDUCED_TYPENAME boost::enable_if<optional_detail::is_optional_val_init_candidate<T, Expr>, optional&>::type
977 operator= ( Expr&& expr )
979 this->assign_expr(boost::forward<Expr>(expr),boost::addressof(expr));
985 optional& operator= ( Expr const& expr )
987 this->assign_expr(expr,boost::addressof(expr));
990 #endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
991 #endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
993 // Copy-assigns from another convertible optional<U> (converts && deep-copies the rhs value)
994 // Requires a valid conversion from U to T.
995 // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
997 optional& operator= ( optional<U> const& rhs )
1003 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1004 // Move-assigns from another convertible optional<U> (converts && deep-moves the rhs value)
1005 // Requires a valid conversion from U to T.
1006 // Basic Guarantee: If T::T( U && ) throws, this is left UNINITIALIZED
1008 optional& operator= ( optional<U> && rhs )
1010 this->assign(boost::move(rhs));
1015 // Assigns from another optional<T> (deep-copies the rhs value)
1016 // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
1017 // (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
1018 #ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
1019 optional& operator= ( optional const& rhs ) = default;
1021 optional& operator= ( optional const& rhs )
1023 this->assign( static_cast<base const&>(rhs) ) ;
1028 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1029 // Assigns from another optional<T> (deep-moves the rhs value)
1030 #ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
1031 optional& operator= ( optional && ) = default;
1033 optional& operator= ( optional && rhs )
1034 BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
1036 this->assign( static_cast<base &&>(rhs) ) ;
1041 #endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1043 #ifndef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
1045 // Assigns from a T (deep-moves/copies the rhs value)
1046 template <typename T_>
1047 BOOST_DEDUCED_TYPENAME boost::enable_if<boost::is_same<T, BOOST_DEDUCED_TYPENAME boost::decay<T_>::type>, optional&>::type
1048 operator= ( T_&& val )
1050 this->assign( boost::forward<T_>(val) ) ;
1056 // Assigns from a T (deep-copies the rhs value)
1057 // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
1058 optional& operator= ( argument_type val )
1060 this->assign( val ) ;
1064 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1065 // Assigns from a T (deep-moves the rhs value)
1066 optional& operator= ( rval_reference_type val )
1068 this->assign( boost::move(val) ) ;
1073 #endif // BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
1075 // Assigns from a "none"
1076 // Which destroys the current value, if any, leaving this UNINITIALIZED
1077 // No-throw (assuming T::~T() doesn't)
1078 optional& operator= ( none_t none_ ) BOOST_NOEXCEPT
1080 this->assign( none_ ) ;
1084 #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1085 // Constructs in-place
1086 // upon exception *this is always uninitialized
1087 template<class... Args>
1088 void emplace ( Args&&... args )
1090 this->emplace_assign( boost::forward<Args>(args)... );
1093 template<class... Args>
1094 explicit optional ( in_place_init_t, Args&&... args )
1095 : base( in_place_init, boost::forward<Args>(args)... )
1098 template<class... Args>
1099 explicit optional ( in_place_init_if_t, bool cond, Args&&... args )
1100 : base( in_place_init_if, cond, boost::forward<Args>(args)... )
1103 #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
1105 void emplace ( Arg&& arg )
1107 this->emplace_assign( boost::forward<Arg>(arg) );
1112 this->emplace_assign();
1115 template<class Args>
1116 explicit optional ( in_place_init_t, Args&& args )
1117 : base( in_place_init, boost::forward<Args>(args) )
1120 explicit optional ( in_place_init_t )
1121 : base( in_place_init )
1124 template<class Args>
1125 explicit optional ( in_place_init_if_t, bool cond, Args&& args )
1126 : base( in_place_init_if, cond, boost::forward<Args>(args) )
1129 explicit optional ( in_place_init_if_t, bool cond )
1130 : base( in_place_init_if, cond )
1134 void emplace ( const Arg& arg )
1136 this->emplace_assign( arg );
1140 void emplace ( Arg& arg )
1142 this->emplace_assign( arg );
1147 this->emplace_assign();
1151 explicit optional ( in_place_init_t, const Arg& arg )
1152 : base( in_place_init, arg )
1156 explicit optional ( in_place_init_t, Arg& arg )
1157 : base( in_place_init, arg )
1160 explicit optional ( in_place_init_t )
1161 : base( in_place_init )
1165 explicit optional ( in_place_init_if_t, bool cond, const Arg& arg )
1166 : base( in_place_init_if, cond, arg )
1170 explicit optional ( in_place_init_if_t, bool cond, Arg& arg )
1171 : base( in_place_init_if, cond, arg )
1174 explicit optional ( in_place_init_if_t, bool cond )
1175 : base( in_place_init_if, cond )
1179 void swap( optional & arg )
1180 BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
1182 // allow for Koenig lookup
1183 boost::swap(*this, arg);
1187 // Returns a reference to the value if this is initialized, otherwise,
1188 // the behaviour is UNDEFINED
1190 reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
1191 reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
1193 // Returns a copy of the value if this is initialized, 'v' otherwise
1194 reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
1195 reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; }
1197 // Returns a pointer to the value if this is initialized, otherwise,
1198 // the behaviour is UNDEFINED
1200 pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
1201 pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
1203 // Returns a reference to the value if this is initialized, otherwise,
1204 // the behaviour is UNDEFINED
1206 #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
1207 reference_const_type operator *() const& { return this->get() ; }
1208 reference_type operator *() & { return this->get() ; }
1209 reference_type_of_temporary_wrapper operator *() && { return boost::move(this->get()) ; }
1211 reference_const_type operator *() const { return this->get() ; }
1212 reference_type operator *() { return this->get() ; }
1213 #endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS
1215 #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
1216 reference_const_type value() const&
1218 if (this->is_initialized())
1219 return this->get() ;
1221 throw_exception(bad_optional_access());
1224 reference_type value() &
1226 if (this->is_initialized())
1227 return this->get() ;
1229 throw_exception(bad_optional_access());
1232 reference_type_of_temporary_wrapper value() &&
1234 if (this->is_initialized())
1235 return boost::move(this->get()) ;
1237 throw_exception(bad_optional_access());
1241 reference_const_type value() const
1243 if (this->is_initialized())
1244 return this->get() ;
1246 throw_exception(bad_optional_access());
1249 reference_type value()
1251 if (this->is_initialized())
1252 return this->get() ;
1254 throw_exception(bad_optional_access());
1259 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
1261 value_type value_or ( U&& v ) const&
1263 if (this->is_initialized())
1266 return boost::forward<U>(v);
1270 value_type value_or ( U&& v ) &&
1272 if (this->is_initialized())
1273 return boost::move(get());
1275 return boost::forward<U>(v);
1277 #elif !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1279 value_type value_or ( U&& v ) const
1281 if (this->is_initialized())
1284 return boost::forward<U>(v);
1288 value_type value_or ( U const& v ) const
1290 if (this->is_initialized())
1297 value_type value_or ( U& v ) const
1299 if (this->is_initialized())
1307 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
1308 template <typename F>
1309 value_type value_or_eval ( F f ) const&
1311 if (this->is_initialized())
1317 template <typename F>
1318 value_type value_or_eval ( F f ) &&
1320 if (this->is_initialized())
1321 return boost::move(get());
1326 template <typename F>
1327 value_type value_or_eval ( F f ) const
1329 if (this->is_initialized())
1336 bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; }
1338 BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
1341 } // namespace boost
1343 #endif // BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL
1347 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1351 BOOST_STATIC_ASSERT_MSG(sizeof(T) == 0, "Optional rvalue references are illegal.");
1355 } // namespace boost
1357 #ifndef BOOST_OPTIONAL_CONFIG_DONT_SPECIALIZE_OPTIONAL_REFS
1358 # include <boost/optional/detail/optional_reference_spec.hpp>
1363 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1367 optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type> make_optional ( T && v )
1369 return optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type>(boost::forward<T>(v));
1372 // Returns optional<T>(cond,v)
1375 optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type> make_optional ( bool cond, T && v )
1377 return optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type>(cond,boost::forward<T>(v));
1382 // Returns optional<T>(v)
1385 optional<T> make_optional ( T const& v )
1387 return optional<T>(v);
1390 // Returns optional<T>(cond,v)
1393 optional<T> make_optional ( bool cond, T const& v )
1395 return optional<T>(cond,v);
1398 #endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1400 // Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
1404 BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
1405 get ( optional<T> const& opt )
1412 BOOST_DEDUCED_TYPENAME optional<T>::reference_type
1413 get ( optional<T>& opt )
1418 // Returns a pointer to the value if this is initialized, otherwise, returns NULL.
1422 BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
1423 get ( optional<T> const* opt )
1425 return opt->get_ptr() ;
1430 BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
1431 get ( optional<T>* opt )
1433 return opt->get_ptr() ;
1436 // Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
1440 BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
1441 get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v )
1443 return opt.get_value_or(v) ;
1448 BOOST_DEDUCED_TYPENAME optional<T>::reference_type
1449 get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v )
1451 return opt.get_value_or(v) ;
1454 // Returns a pointer to the value if this is initialized, otherwise, returns NULL.
1458 BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
1459 get_pointer ( optional<T> const& opt )
1461 return opt.get_ptr() ;
1466 BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
1467 get_pointer ( optional<T>& opt )
1469 return opt.get_ptr() ;
1472 } // namespace boost
1476 // The following declaration prevents a bug where operator safe-bool is used upon streaming optional object if you forget the IO header.
1477 template<class CharType, class CharTrait>
1478 std::basic_ostream<CharType, CharTrait>&
1479 operator<<(std::basic_ostream<CharType, CharTrait>& os, optional_detail::optional_tag const&)
1481 BOOST_STATIC_ASSERT_MSG(sizeof(CharType) == 0, "If you want to output boost::optional, include header <boost/optional/optional_io.hpp>");
1485 } // namespace boost
1487 #include <boost/optional/detail/optional_relops.hpp>
1488 #include <boost/optional/detail/optional_swap.hpp>
1490 #endif // header guard