1 // Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
2 // Copyright (C) 2014 - 2016 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 #include <boost/assert.hpp>
24 #include <boost/core/addressof.hpp>
25 #include <boost/core/enable_if.hpp>
26 #include <boost/core/explicit_operator_bool.hpp>
27 #include <boost/core/swap.hpp>
28 #include <boost/optional/bad_optional_access.hpp>
29 #include <boost/static_assert.hpp>
30 #include <boost/throw_exception.hpp>
31 #include <boost/type.hpp>
32 #include <boost/type_traits/alignment_of.hpp>
33 #include <boost/type_traits/conditional.hpp>
34 #include <boost/type_traits/has_nothrow_constructor.hpp>
35 #include <boost/type_traits/type_with_alignment.hpp>
36 #include <boost/type_traits/remove_const.hpp>
37 #include <boost/type_traits/remove_reference.hpp>
38 #include <boost/type_traits/decay.hpp>
39 #include <boost/type_traits/is_base_of.hpp>
40 #include <boost/type_traits/is_constructible.hpp>
41 #include <boost/type_traits/is_lvalue_reference.hpp>
42 #include <boost/type_traits/is_nothrow_move_assignable.hpp>
43 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
44 #include <boost/type_traits/is_rvalue_reference.hpp>
45 #include <boost/type_traits/is_same.hpp>
46 #include <boost/move/utility.hpp>
47 #include <boost/none.hpp>
48 #include <boost/utility/compare_pointees.hpp>
50 #include <boost/optional/optional_fwd.hpp>
51 #include <boost/optional/detail/optional_config.hpp>
52 #include <boost/optional/detail/optional_factory_support.hpp>
53 #include <boost/optional/detail/optional_aligned_storage.hpp>
55 #ifdef BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL
56 #include <boost/optional/detail/old_optional_implementation.hpp>
60 namespace optional_ns {
62 // a tag for in-place initialization of contained value
63 struct in_place_init_t
66 explicit in_place_init_t(init_tag){}
68 const in_place_init_t in_place_init ((in_place_init_t::init_tag()));
70 // a tag for conditional in-place initialization of contained value
71 struct in_place_init_if_t
74 explicit in_place_init_if_t(init_tag){}
76 const in_place_init_if_t in_place_init_if ((in_place_init_if_t::init_tag()));
78 } // namespace optional_ns
80 using optional_ns::in_place_init_t;
81 using optional_ns::in_place_init;
82 using optional_ns::in_place_init_if_t;
83 using optional_ns::in_place_init_if;
85 namespace optional_detail {
87 struct optional_tag {} ;
91 class optional_base : public optional_tag
95 typedef aligned_storage<T> storage_type ;
96 typedef optional_base<T> this_type ;
100 typedef T value_type ;
103 typedef T & reference_type ;
104 typedef T const& reference_const_type ;
105 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
106 typedef T && rval_reference_type ;
107 typedef T && reference_type_of_temporary_wrapper ;
109 typedef T * pointer_type ;
110 typedef T const* pointer_const_type ;
111 typedef T const& argument_type ;
113 // Creates an optional<T> uninitialized.
117 m_initialized(false) {}
119 // Creates an optional<T> uninitialized.
121 optional_base ( none_t )
123 m_initialized(false) {}
125 // Creates an optional<T> initialized with 'val'.
126 // Can throw if T::T(T const&) does
127 optional_base ( argument_type val )
134 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
135 // move-construct an optional<T> initialized from an rvalue-ref to 'val'.
136 // Can throw if T::T(T&&) does
137 optional_base ( rval_reference_type val )
141 construct( boost::move(val) );
145 // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>.
146 // Can throw if T::T(T const&) does
147 optional_base ( bool cond, argument_type val )
155 // Creates a deep copy of another optional<T>
156 // Can throw if T::T(T const&) does
157 optional_base ( optional_base const& rhs )
161 if ( rhs.is_initialized() )
162 construct(rhs.get_impl());
165 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
166 // Creates a deep move of another optional<T>
167 // Can throw if T::T(T&&) does
168 optional_base ( optional_base&& rhs )
172 if ( rhs.is_initialized() )
173 construct( boost::move(rhs.get_impl()) );
177 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
179 template<class Expr, class PtrExpr>
180 explicit optional_base ( Expr&& expr, PtrExpr const* tag )
184 construct(boost::forward<Expr>(expr),tag);
188 // This is used for both converting and in-place constructions.
189 // Derived classes use the 'tag' to select the appropriate
190 // implementation (the correct 'construct()' overload)
192 explicit optional_base ( Expr const& expr, Expr const* tag )
202 // No-throw (assuming T::~T() doesn't)
203 ~optional_base() { destroy() ; }
205 // Assigns from another optional<T> (deep-copies the rhs value)
206 void assign ( optional_base const& rhs )
208 if (is_initialized())
210 if ( rhs.is_initialized() )
211 assign_value(rhs.get_impl());
216 if ( rhs.is_initialized() )
217 construct(rhs.get_impl());
221 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
222 // Assigns from another optional<T> (deep-moves the rhs value)
223 void assign ( optional_base&& rhs )
225 if (is_initialized())
227 if ( rhs.is_initialized() )
228 assign_value( boost::move(rhs.get_impl()) );
233 if ( rhs.is_initialized() )
234 construct(boost::move(rhs.get_impl()));
239 // Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
241 void assign ( optional<U> const& rhs )
243 if (is_initialized())
245 if ( rhs.is_initialized() )
246 #ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
247 assign_value( rhs.get() );
249 assign_value( static_cast<value_type>(rhs.get()) );
256 if ( rhs.is_initialized() )
257 #ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
258 construct(rhs.get());
260 construct(static_cast<value_type>(rhs.get()));
265 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
266 // move-assigns from another _convertible_ optional<U> (deep-moves from the rhs value)
268 void assign ( optional<U>&& rhs )
270 typedef BOOST_DEDUCED_TYPENAME optional<U>::rval_reference_type ref_type;
271 if (is_initialized())
273 if ( rhs.is_initialized() )
274 assign_value( static_cast<ref_type>(rhs.get()) );
279 if ( rhs.is_initialized() )
280 construct(static_cast<ref_type>(rhs.get()));
285 // Assigns from a T (deep-copies the rhs value)
286 void assign ( argument_type val )
288 if (is_initialized())
293 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
294 // Assigns from a T (deep-moves the rhs value)
295 void assign ( rval_reference_type val )
297 if (is_initialized())
298 assign_value( boost::move(val) );
299 else construct( boost::move(val) );
303 // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
304 // No-throw (assuming T::~T() doesn't)
305 void assign ( none_t ) BOOST_NOEXCEPT { destroy(); }
307 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
309 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
310 template<class Expr, class ExprPtr>
311 void assign_expr ( Expr&& expr, ExprPtr const* tag )
313 if (is_initialized())
314 assign_expr_to_initialized(boost::forward<Expr>(expr),tag);
315 else construct(boost::forward<Expr>(expr),tag);
319 void assign_expr ( Expr const& expr, Expr const* tag )
321 if (is_initialized())
322 assign_expr_to_initialized(expr,tag);
323 else construct(expr,tag);
331 // **DEPPRECATED** Destroys the current value, if any, leaving this UNINITIALIZED
332 // No-throw (assuming T::~T() doesn't)
333 void reset() BOOST_NOEXCEPT { destroy(); }
335 // **DEPPRECATED** Replaces the current value -if any- with 'val'
336 void reset ( argument_type val ) { assign(val); }
338 // Returns a pointer to the value if this is initialized, otherwise,
341 pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
342 pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; }
344 bool is_initialized() const { return m_initialized ; }
348 void construct ( argument_type val )
350 ::new (m_storage.address()) value_type(val) ;
351 m_initialized = true ;
354 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
355 void construct ( rval_reference_type val )
357 ::new (m_storage.address()) value_type( boost::move(val) ) ;
358 m_initialized = true ;
363 #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
364 // Constructs in-place
365 // upon exception *this is always uninitialized
366 template<class... Args>
367 void construct ( in_place_init_t, Args&&... args )
369 ::new (m_storage.address()) value_type( boost::forward<Args>(args)... ) ;
370 m_initialized = true ;
373 template<class... Args>
374 void emplace_assign ( Args&&... args )
377 construct(in_place_init, boost::forward<Args>(args)...);
380 template<class... Args>
381 explicit optional_base ( in_place_init_t, Args&&... args )
385 construct(in_place_init, boost::forward<Args>(args)...);
388 template<class... Args>
389 explicit optional_base ( in_place_init_if_t, bool cond, Args&&... args )
394 construct(in_place_init, boost::forward<Args>(args)...);
396 #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
398 void construct ( in_place_init_t, Arg&& arg )
400 ::new (m_storage.address()) value_type( boost::forward<Arg>(arg) );
401 m_initialized = true ;
404 void construct ( in_place_init_t )
406 ::new (m_storage.address()) value_type();
407 m_initialized = true ;
411 void emplace_assign ( Arg&& arg )
414 construct(in_place_init, boost::forward<Arg>(arg)) ;
417 void emplace_assign ()
420 construct(in_place_init) ;
424 explicit optional_base ( in_place_init_t, Arg&& arg )
428 construct(in_place_init, boost::forward<Arg>(arg));
431 explicit optional_base ( in_place_init_t )
435 construct(in_place_init);
439 explicit optional_base ( in_place_init_if_t, bool cond, Arg&& arg )
444 construct(in_place_init, boost::forward<Arg>(arg));
447 explicit optional_base ( in_place_init_if_t, bool cond )
452 construct(in_place_init);
458 void construct ( in_place_init_t, const Arg& arg )
460 ::new (m_storage.address()) value_type( arg );
461 m_initialized = true ;
465 void construct ( in_place_init_t, Arg& arg )
467 ::new (m_storage.address()) value_type( arg );
468 m_initialized = true ;
471 void construct ( in_place_init_t )
473 ::new (m_storage.address()) value_type();
474 m_initialized = true ;
478 void emplace_assign ( const Arg& arg )
481 construct(in_place_init, arg);
485 void emplace_assign ( Arg& arg )
488 construct(in_place_init, arg);
491 void emplace_assign ()
494 construct(in_place_init);
498 explicit optional_base ( in_place_init_t, const Arg& arg )
499 : m_initialized(false)
501 construct(in_place_init, arg);
505 explicit optional_base ( in_place_init_t, Arg& arg )
506 : m_initialized(false)
508 construct(in_place_init, arg);
511 explicit optional_base ( in_place_init_t )
512 : m_initialized(false)
514 construct(in_place_init);
518 explicit optional_base ( in_place_init_if_t, bool cond, const Arg& arg )
519 : m_initialized(false)
522 construct(in_place_init, arg);
526 explicit optional_base ( in_place_init_if_t, bool cond, Arg& arg )
527 : m_initialized(false)
530 construct(in_place_init, arg);
533 explicit optional_base ( in_place_init_if_t, bool cond )
534 : m_initialized(false)
537 construct(in_place_init);
541 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
543 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
544 // Constructs in-place using the given factory
546 void construct ( Expr&& factory, in_place_factory_base const* )
548 boost_optional_detail::construct<value_type>(factory, m_storage.address());
549 m_initialized = true ;
552 // Constructs in-place using the given typed factory
554 void construct ( Expr&& factory, typed_in_place_factory_base const* )
556 factory.apply(m_storage.address()) ;
557 m_initialized = true ;
561 void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag )
564 construct(factory,tag);
567 // Constructs in-place using the given typed factory
569 void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag )
572 construct(factory,tag);
576 // Constructs in-place using the given factory
578 void construct ( Expr const& factory, in_place_factory_base const* )
580 boost_optional_detail::construct<value_type>(factory, m_storage.address());
581 m_initialized = true ;
584 // Constructs in-place using the given typed factory
586 void construct ( Expr const& factory, typed_in_place_factory_base const* )
588 factory.apply(m_storage.address()) ;
589 m_initialized = true ;
593 void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag )
596 construct(factory,tag);
599 // Constructs in-place using the given typed factory
601 void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag )
604 construct(factory,tag);
610 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
611 // Constructs using any expression implicitly convertible to the single argument
612 // of a one-argument T constructor.
613 // Converting constructions of optional<T> from optional<U> uses this function with
614 // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
616 void construct ( Expr&& expr, void const* )
618 new (m_storage.address()) value_type(boost::forward<Expr>(expr)) ;
619 m_initialized = true ;
622 // Assigns using a form any expression implicitly convertible to the single argument
623 // of a T's assignment operator.
624 // Converting assignments of optional<T> from optional<U> uses this function with
625 // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
627 void assign_expr_to_initialized ( Expr&& expr, void const* )
629 assign_value( boost::forward<Expr>(expr) );
632 // Constructs using any expression implicitly convertible to the single argument
633 // of a one-argument T constructor.
634 // Converting constructions of optional<T> from optional<U> uses this function with
635 // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
637 void construct ( Expr const& expr, void const* )
639 new (m_storage.address()) value_type(expr) ;
640 m_initialized = true ;
643 // Assigns using a form any expression implicitly convertible to the single argument
644 // of a T's assignment operator.
645 // Converting assignments of optional<T> from optional<U> uses this function with
646 // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
648 void assign_expr_to_initialized ( Expr const& expr, void const* )
655 #ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
656 // BCB5.64 (and probably lower versions) workaround.
657 // The in-place factories are supported by means of catch-all constructors
658 // and assignment operators (the functions are parameterized in terms of
659 // an arbitrary 'Expr' type)
660 // This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U>
661 // to the 'Expr'-taking functions even though explicit overloads are present for them.
662 // Thus, the following overload is needed to properly handle the case when the 'lhs'
663 // is another optional.
665 // For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error
666 // instead of choosing the wrong overload
668 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
669 // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
671 void construct ( Expr&& expr, optional_tag const* )
673 if ( expr.is_initialized() )
675 // An exception can be thrown here.
676 // It it happens, THIS will be left uninitialized.
677 new (m_storage.address()) value_type(boost::move(expr.get())) ;
678 m_initialized = true ;
682 // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
684 void construct ( Expr const& expr, optional_tag const* )
686 if ( expr.is_initialized() )
688 // An exception can be thrown here.
689 // It it happens, THIS will be left uninitialized.
690 new (m_storage.address()) value_type(expr.get()) ;
691 m_initialized = true ;
695 #endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
697 void assign_value ( argument_type val ) { get_impl() = val; }
698 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
699 void assign_value ( rval_reference_type val ) { get_impl() = static_cast<rval_reference_type>(val); }
708 reference_const_type get_impl() const { return m_storage.ref() ; }
709 reference_type get_impl() { return m_storage.ref() ; }
711 pointer_const_type get_ptr_impl() const { return m_storage.ptr_ref(); }
712 pointer_type get_ptr_impl() { return m_storage.ptr_ref(); }
716 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1600)
717 void destroy_impl ( ) { m_storage.ptr_ref()->~T() ; m_initialized = false ; }
719 void destroy_impl ( ) { m_storage.ref().T::~T() ; m_initialized = false ; }
723 storage_type m_storage ;
726 // definition of metafunciton is_optional_val_init_candidate
727 template <typename U>
728 struct is_optional_related
729 : boost::conditional< boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
730 || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, none_t>::value
731 || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, in_place_init_t>::value
732 || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, in_place_init_if_t>::value,
733 boost::true_type, boost::false_type>::type
736 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40500) && !defined(__SUNPRO_CC)
737 // this condition is a copy paste from is_constructible.hpp
738 // I also disable SUNPRO, as it seems not to support type_traits correctly
740 template <typename T, typename U>
741 struct is_convertible_to_T_or_factory
742 : boost::conditional< boost::is_base_of<boost::in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
743 || boost::is_base_of<boost::typed_in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
744 || boost::is_constructible<T, U&&>::value
745 , boost::true_type, boost::false_type>::type
750 #define BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT
752 template <typename, typename>
753 struct is_convertible_to_T_or_factory : boost::true_type
756 #endif // is_convertible condition
758 template <typename T, typename U>
759 struct is_optional_val_init_candidate
760 : boost::conditional< !is_optional_related<U>::value && is_convertible_to_T_or_factory<T, U>::value
761 , boost::true_type, boost::false_type>::type
764 } // namespace optional_detail
767 class optional : public optional_detail::optional_base<T>
769 typedef optional_detail::optional_base<T> base ;
773 typedef optional<T> this_type ;
775 typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ;
776 typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ;
777 typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
778 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
779 typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type rval_reference_type ;
780 typedef BOOST_DEDUCED_TYPENAME base::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ;
782 typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ;
783 typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ;
784 typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
786 // Creates an optional<T> uninitialized.
788 optional() BOOST_NOEXCEPT : base() {}
790 // Creates an optional<T> uninitialized.
792 optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {}
794 // Creates an optional<T> initialized with 'val'.
795 // Can throw if T::T(T const&) does
796 optional ( argument_type val ) : base(val) {}
798 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
799 // Creates an optional<T> initialized with 'move(val)'.
800 // Can throw if T::T(T &&) does
801 optional ( rval_reference_type val ) : base( boost::forward<T>(val) )
805 // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
806 // Can throw if T::T(T const&) does
807 optional ( bool cond, argument_type val ) : base(cond,val) {}
809 // NOTE: MSVC needs templated versions first
811 // Creates a deep copy of another convertible optional<U>
812 // Requires a valid conversion from U to T.
813 // Can throw if T::T(U const&) does
815 explicit optional ( optional<U> const& rhs )
819 if ( rhs.is_initialized() )
820 this->construct(rhs.get());
823 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
824 // Creates a deep move of another convertible optional<U>
825 // Requires a valid conversion from U to T.
826 // Can throw if T::T(U&&) does
828 explicit optional ( optional<U> && rhs )
832 if ( rhs.is_initialized() )
833 this->construct( boost::move(rhs.get()) );
837 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
838 // Creates an optional<T> with an expression which can be either
839 // (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
840 // (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
841 // (c) Any expression implicitly convertible to the single type
842 // of a one-argument T's constructor.
843 // (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
844 // even though explicit overloads are present for these.
845 // Depending on the above some T ctor is called.
846 // Can throw if the resolved T ctor throws.
847 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
851 explicit optional ( Expr&& expr,
852 BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_val_init_candidate<T, Expr> >::type* = 0
854 : base(boost::forward<Expr>(expr),boost::addressof(expr))
859 explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
860 #endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
861 #endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
863 // Creates a deep copy of another optional<T>
864 // Can throw if T::T(T const&) does
865 optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
867 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
868 // Creates a deep move of another optional<T>
869 // Can throw if T::T(T&&) does
870 optional ( optional && rhs )
871 BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
872 : base( boost::move(rhs) )
877 #if BOOST_WORKAROUND(_MSC_VER, <= 1600)
878 // On old MSVC compilers the implicitly declared dtor is not called
883 #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
884 // Assigns from an expression. See corresponding constructor.
885 // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
886 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
889 BOOST_DEDUCED_TYPENAME boost::enable_if<optional_detail::is_optional_val_init_candidate<T, Expr>, optional&>::type
890 operator= ( Expr&& expr )
892 this->assign_expr(boost::forward<Expr>(expr),boost::addressof(expr));
898 optional& operator= ( Expr const& expr )
900 this->assign_expr(expr,boost::addressof(expr));
903 #endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
904 #endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
906 // Copy-assigns from another convertible optional<U> (converts && deep-copies the rhs value)
907 // Requires a valid conversion from U to T.
908 // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
910 optional& operator= ( optional<U> const& rhs )
916 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
917 // Move-assigns from another convertible optional<U> (converts && deep-moves the rhs value)
918 // Requires a valid conversion from U to T.
919 // Basic Guarantee: If T::T( U && ) throws, this is left UNINITIALIZED
921 optional& operator= ( optional<U> && rhs )
923 this->assign(boost::move(rhs));
928 // Assigns from another optional<T> (deep-copies the rhs value)
929 // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
930 // (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
931 optional& operator= ( optional const& rhs )
933 this->assign( static_cast<base const&>(rhs) ) ;
937 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
938 // Assigns from another optional<T> (deep-moves the rhs value)
939 optional& operator= ( optional && rhs )
940 BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
942 this->assign( static_cast<base &&>(rhs) ) ;
947 // Assigns from a T (deep-copies the rhs value)
948 // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
949 optional& operator= ( argument_type val )
951 this->assign( val ) ;
955 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
956 // Assigns from a T (deep-moves the rhs value)
957 optional& operator= ( rval_reference_type val )
959 this->assign( boost::move(val) ) ;
964 // Assigns from a "none"
965 // Which destroys the current value, if any, leaving this UNINITIALIZED
966 // No-throw (assuming T::~T() doesn't)
967 optional& operator= ( none_t none_ ) BOOST_NOEXCEPT
969 this->assign( none_ ) ;
973 #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
974 // Constructs in-place
975 // upon exception *this is always uninitialized
976 template<class... Args>
977 void emplace ( Args&&... args )
979 this->emplace_assign( boost::forward<Args>(args)... );
982 template<class... Args>
983 explicit optional ( in_place_init_t, Args&&... args )
984 : base( in_place_init, boost::forward<Args>(args)... )
987 template<class... Args>
988 explicit optional ( in_place_init_if_t, bool cond, Args&&... args )
989 : base( in_place_init_if, cond, boost::forward<Args>(args)... )
992 #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
994 void emplace ( Arg&& arg )
996 this->emplace_assign( boost::forward<Arg>(arg) );
1001 this->emplace_assign();
1004 template<class Args>
1005 explicit optional ( in_place_init_t, Args&& args )
1006 : base( in_place_init, boost::forward<Args>(args) )
1009 explicit optional ( in_place_init_t )
1010 : base( in_place_init )
1013 template<class Args>
1014 explicit optional ( in_place_init_if_t, bool cond, Args&& args )
1015 : base( in_place_init_if, cond, boost::forward<Args>(args) )
1018 explicit optional ( in_place_init_if_t, bool cond )
1019 : base( in_place_init_if, cond )
1023 void emplace ( const Arg& arg )
1025 this->emplace_assign( arg );
1029 void emplace ( Arg& arg )
1031 this->emplace_assign( arg );
1036 this->emplace_assign();
1040 explicit optional ( in_place_init_t, const Arg& arg )
1041 : base( in_place_init, arg )
1045 explicit optional ( in_place_init_t, Arg& arg )
1046 : base( in_place_init, arg )
1049 explicit optional ( in_place_init_t )
1050 : base( in_place_init )
1054 explicit optional ( in_place_init_if_t, bool cond, const Arg& arg )
1055 : base( in_place_init_if, cond, arg )
1059 explicit optional ( in_place_init_if_t, bool cond, Arg& arg )
1060 : base( in_place_init_if, cond, arg )
1063 explicit optional ( in_place_init_if_t, bool cond )
1064 : base( in_place_init_if, cond )
1068 void swap( optional & arg )
1069 BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
1071 // allow for Koenig lookup
1072 boost::swap(*this, arg);
1076 // Returns a reference to the value if this is initialized, otherwise,
1077 // the behaviour is UNDEFINED
1079 reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
1080 reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
1082 // Returns a copy of the value if this is initialized, 'v' otherwise
1083 reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
1084 reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; }
1086 // Returns a pointer to the value if this is initialized, otherwise,
1087 // the behaviour is UNDEFINED
1089 pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
1090 pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
1092 // Returns a reference to the value if this is initialized, otherwise,
1093 // the behaviour is UNDEFINED
1095 #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
1096 reference_const_type operator *() const& { return this->get() ; }
1097 reference_type operator *() & { return this->get() ; }
1098 reference_type_of_temporary_wrapper operator *() && { return boost::move(this->get()) ; }
1100 reference_const_type operator *() const { return this->get() ; }
1101 reference_type operator *() { return this->get() ; }
1102 #endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS
1104 #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
1105 reference_const_type value() const&
1107 if (this->is_initialized())
1108 return this->get() ;
1110 throw_exception(bad_optional_access());
1113 reference_type value() &
1115 if (this->is_initialized())
1116 return this->get() ;
1118 throw_exception(bad_optional_access());
1121 reference_type_of_temporary_wrapper value() &&
1123 if (this->is_initialized())
1124 return boost::move(this->get()) ;
1126 throw_exception(bad_optional_access());
1130 reference_const_type value() const
1132 if (this->is_initialized())
1133 return this->get() ;
1135 throw_exception(bad_optional_access());
1138 reference_type value()
1140 if (this->is_initialized())
1141 return this->get() ;
1143 throw_exception(bad_optional_access());
1148 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
1150 value_type value_or ( U&& v ) const&
1152 if (this->is_initialized())
1155 return boost::forward<U>(v);
1159 value_type value_or ( U&& v ) &&
1161 if (this->is_initialized())
1162 return boost::move(get());
1164 return boost::forward<U>(v);
1166 #elif !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1168 value_type value_or ( U&& v ) const
1170 if (this->is_initialized())
1173 return boost::forward<U>(v);
1177 value_type value_or ( U const& v ) const
1179 if (this->is_initialized())
1186 value_type value_or ( U& v ) const
1188 if (this->is_initialized())
1196 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
1197 template <typename F>
1198 value_type value_or_eval ( F f ) const&
1200 if (this->is_initialized())
1206 template <typename F>
1207 value_type value_or_eval ( F f ) &&
1209 if (this->is_initialized())
1210 return boost::move(get());
1215 template <typename F>
1216 value_type value_or_eval ( F f ) const
1218 if (this->is_initialized())
1225 bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; }
1227 BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
1230 } // namespace boost
1232 #endif // BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL
1236 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1240 BOOST_STATIC_ASSERT_MSG(sizeof(T) == 0, "Optional rvalue references are illegal.");
1244 } // namespace boost
1246 #ifndef BOOST_OPTIONAL_CONFIG_DONT_SPECIALIZE_OPTIONAL_REFS
1247 # include <boost/optional/detail/optional_reference_spec.hpp>
1252 // Returns optional<T>(v)
1255 optional<T> make_optional ( T const& v )
1257 return optional<T>(v);
1260 // Returns optional<T>(cond,v)
1263 optional<T> make_optional ( bool cond, T const& v )
1265 return optional<T>(cond,v);
1268 // Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
1272 BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
1273 get ( optional<T> const& opt )
1280 BOOST_DEDUCED_TYPENAME optional<T>::reference_type
1281 get ( optional<T>& opt )
1286 // Returns a pointer to the value if this is initialized, otherwise, returns NULL.
1290 BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
1291 get ( optional<T> const* opt )
1293 return opt->get_ptr() ;
1298 BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
1299 get ( optional<T>* opt )
1301 return opt->get_ptr() ;
1304 // Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
1308 BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
1309 get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v )
1311 return opt.get_value_or(v) ;
1316 BOOST_DEDUCED_TYPENAME optional<T>::reference_type
1317 get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v )
1319 return opt.get_value_or(v) ;
1322 // Returns a pointer to the value if this is initialized, otherwise, returns NULL.
1326 BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
1327 get_pointer ( optional<T> const& opt )
1329 return opt.get_ptr() ;
1334 BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
1335 get_pointer ( optional<T>& opt )
1337 return opt.get_ptr() ;
1340 } // namespace boost
1344 // The following declaration prevents a bug where operator safe-bool is used upon streaming optional object if you forget the IO header.
1345 template<class CharType, class CharTrait>
1346 std::basic_ostream<CharType, CharTrait>&
1347 operator<<(std::basic_ostream<CharType, CharTrait>& os, optional_detail::optional_tag const&)
1349 BOOST_STATIC_ASSERT_MSG(sizeof(CharType) == 0, "If you want to output boost::optional, include header <boost/optional/optional_io.hpp>");
1353 } // namespace boost
1355 #include <boost/optional/detail/optional_relops.hpp>
1356 #include <boost/optional/detail/optional_swap.hpp>
1358 #endif // header guard