1 // Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
2 // Copyright (C) 2014 - 2016 Andrzej Krzemienski.
3 //
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)
7 //
8 // See http://www.boost.org/libs/optional for documentation.
9 //
10 // You are welcome to contact the author at:
11 //  fernando_cacciola@hotmail.com
12 //
13 // Revisions:
14 // 27 Apr 2008 (improved swap) Fernando Cacciola, Niels Dekker, Thorsten Ottosen
15 // 05 May 2014 (Added move semantics) Andrzej Krzemienski
16 //
17 #ifndef BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
18 #define BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
19 
20 #include <new>
21 #include <iosfwd>
22 
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>
49 
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>
54 
55 #ifdef BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL
56 #include <boost/optional/detail/old_optional_implementation.hpp>
57 #else
58 namespace boost {
59 
60 namespace optional_ns {
61 
62 // a tag for in-place initialization of contained value
63 struct in_place_init_t
64 {
65   struct init_tag{};
in_place_init_tboost::optional_ns::in_place_init_t66   explicit in_place_init_t(init_tag){}
67 };
68 const in_place_init_t in_place_init ((in_place_init_t::init_tag()));
69 
70 // a tag for conditional in-place initialization of contained value
71 struct in_place_init_if_t
72 {
73   struct init_tag{};
in_place_init_if_tboost::optional_ns::in_place_init_if_t74   explicit in_place_init_if_t(init_tag){}
75 };
76 const in_place_init_if_t in_place_init_if ((in_place_init_if_t::init_tag()));
77 
78 } // namespace optional_ns
79 
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;
84 
85 namespace optional_detail {
86 
87 struct optional_tag {} ;
88 
89 
90 template<class T>
91 class optional_base : public optional_tag
92 {
93   private :
94 
95     typedef aligned_storage<T> storage_type ;
96     typedef optional_base<T> this_type ;
97 
98   protected :
99 
100     typedef T value_type ;
101 
102   protected:
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 ;
108 #endif
109     typedef T *         pointer_type ;
110     typedef T const*    pointer_const_type ;
111     typedef T const&    argument_type ;
112 
113     // Creates an optional<T> uninitialized.
114     // No-throw
optional_base()115     optional_base()
116       :
117       m_initialized(false) {}
118 
119     // Creates an optional<T> uninitialized.
120     // No-throw
optional_base(none_t)121     optional_base ( none_t )
122       :
123       m_initialized(false) {}
124 
125     // Creates an optional<T> initialized with 'val'.
126     // Can throw if T::T(T const&) does
optional_base(argument_type val)127     optional_base ( argument_type val )
128       :
129       m_initialized(false)
130     {
131         construct(val);
132     }
133 
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
optional_base(rval_reference_type val)137     optional_base ( rval_reference_type val )
138       :
139       m_initialized(false)
140     {
141       construct( boost::move(val) );
142     }
143 #endif
144 
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
optional_base(bool cond,argument_type val)147     optional_base ( bool cond, argument_type val )
148       :
149       m_initialized(false)
150     {
151       if ( cond )
152         construct(val);
153     }
154 
155     // Creates a deep copy of another optional<T>
156     // Can throw if T::T(T const&) does
optional_base(optional_base const & rhs)157     optional_base ( optional_base const& rhs )
158       :
159       m_initialized(false)
160     {
161       if ( rhs.is_initialized() )
162         construct(rhs.get_impl());
163     }
164 
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
optional_base(optional_base && rhs)168     optional_base ( optional_base&& rhs )
169       :
170       m_initialized(false)
171     {
172       if ( rhs.is_initialized() )
173         construct( boost::move(rhs.get_impl()) );
174     }
175 #endif
176 
177 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
178 
179     template<class Expr, class PtrExpr>
optional_base(Expr && expr,PtrExpr const * tag)180     explicit optional_base ( Expr&& expr, PtrExpr const* tag )
181       :
182       m_initialized(false)
183     {
184       construct(boost::forward<Expr>(expr),tag);
185     }
186 
187 #else
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)
191     template<class Expr>
optional_base(Expr const & expr,Expr const * tag)192     explicit optional_base ( Expr const& expr, Expr const* tag )
193       :
194       m_initialized(false)
195     {
196       construct(expr,tag);
197     }
198 
199 #endif
200 
201 
202     // No-throw (assuming T::~T() doesn't)
~optional_base()203     ~optional_base() { destroy() ; }
204 
205     // Assigns from another optional<T> (deep-copies the rhs value)
assign(optional_base const & rhs)206     void assign ( optional_base const& rhs )
207     {
208       if (is_initialized())
209       {
210         if ( rhs.is_initialized() )
211              assign_value(rhs.get_impl());
212         else destroy();
213       }
214       else
215       {
216         if ( rhs.is_initialized() )
217           construct(rhs.get_impl());
218       }
219     }
220 
221 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
222     // Assigns from another optional<T> (deep-moves the rhs value)
assign(optional_base && rhs)223     void assign ( optional_base&& rhs )
224     {
225       if (is_initialized())
226       {
227         if ( rhs.is_initialized() )
228              assign_value( boost::move(rhs.get_impl()) );
229         else destroy();
230       }
231       else
232       {
233         if ( rhs.is_initialized() )
234           construct(boost::move(rhs.get_impl()));
235       }
236     }
237 #endif
238 
239     // Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
240     template<class U>
assign(optional<U> const & rhs)241     void assign ( optional<U> const& rhs )
242     {
243       if (is_initialized())
244       {
245         if ( rhs.is_initialized() )
246 #ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
247           assign_value( rhs.get() );
248 #else
249           assign_value( static_cast<value_type>(rhs.get()) );
250 #endif
251 
252         else destroy();
253       }
254       else
255       {
256         if ( rhs.is_initialized() )
257 #ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
258           construct(rhs.get());
259 #else
260           construct(static_cast<value_type>(rhs.get()));
261 #endif
262       }
263     }
264 
265 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
266     // move-assigns from another _convertible_ optional<U> (deep-moves from the rhs value)
267     template<class U>
assign(optional<U> && rhs)268     void assign ( optional<U>&& rhs )
269     {
270       typedef BOOST_DEDUCED_TYPENAME optional<U>::rval_reference_type ref_type;
271       if (is_initialized())
272       {
273         if ( rhs.is_initialized() )
274              assign_value( static_cast<ref_type>(rhs.get()) );
275         else destroy();
276       }
277       else
278       {
279         if ( rhs.is_initialized() )
280           construct(static_cast<ref_type>(rhs.get()));
281       }
282     }
283 #endif
284 
285     // Assigns from a T (deep-copies the rhs value)
assign(argument_type val)286     void assign ( argument_type val )
287     {
288       if (is_initialized())
289            assign_value(val);
290       else construct(val);
291     }
292 
293 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
294     // Assigns from a T (deep-moves the rhs value)
assign(rval_reference_type val)295     void assign ( rval_reference_type val )
296     {
297       if (is_initialized())
298            assign_value( boost::move(val) );
299       else construct( boost::move(val) );
300     }
301 #endif
302 
303     // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
304     // No-throw (assuming T::~T() doesn't)
assign(none_t)305     void assign ( none_t ) BOOST_NOEXCEPT { destroy(); }
306 
307 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
308 
309 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
310     template<class Expr, class ExprPtr>
assign_expr(Expr && expr,ExprPtr const * tag)311     void assign_expr ( Expr&& expr, ExprPtr const* tag )
312     {
313       if (is_initialized())
314         assign_expr_to_initialized(boost::forward<Expr>(expr),tag);
315       else construct(boost::forward<Expr>(expr),tag);
316     }
317 #else
318     template<class Expr>
assign_expr(Expr const & expr,Expr const * tag)319     void assign_expr ( Expr const& expr, Expr const* tag )
320     {
321       if (is_initialized())
322         assign_expr_to_initialized(expr,tag);
323       else construct(expr,tag);
324     }
325 #endif
326 
327 #endif
328 
329   public :
330 
331     // **DEPPRECATED** Destroys the current value, if any, leaving this UNINITIALIZED
332     // No-throw (assuming T::~T() doesn't)
reset()333     void reset() BOOST_NOEXCEPT { destroy(); }
334 
335     // **DEPPRECATED** Replaces the current value -if any- with 'val'
reset(argument_type val)336     void reset ( argument_type val ) { assign(val); }
337 
338     // Returns a pointer to the value if this is initialized, otherwise,
339     // returns NULL.
340     // No-throw
get_ptr() const341     pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
get_ptr()342     pointer_type       get_ptr()       { return m_initialized ? get_ptr_impl() : 0 ; }
343 
is_initialized() const344     bool is_initialized() const { return m_initialized ; }
345 
346   protected :
347 
construct(argument_type val)348     void construct ( argument_type val )
349      {
350        ::new (m_storage.address()) value_type(val) ;
351        m_initialized = true ;
352      }
353 
354 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
construct(rval_reference_type val)355     void construct ( rval_reference_type val )
356      {
357        ::new (m_storage.address()) value_type( boost::move(val) ) ;
358        m_initialized = true ;
359      }
360 #endif
361 
362 
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>
construct(in_place_init_t,Args &&...args)367     void construct ( in_place_init_t, Args&&... args )
368     {
369       ::new (m_storage.address()) value_type( boost::forward<Args>(args)... ) ;
370       m_initialized = true ;
371     }
372 
373     template<class... Args>
emplace_assign(Args &&...args)374     void emplace_assign ( Args&&... args )
375     {
376       destroy();
377       construct(in_place_init, boost::forward<Args>(args)...);
378     }
379 
380     template<class... Args>
optional_base(in_place_init_t,Args &&...args)381     explicit optional_base ( in_place_init_t, Args&&... args )
382       :
383       m_initialized(false)
384     {
385       construct(in_place_init, boost::forward<Args>(args)...);
386     }
387 
388     template<class... Args>
optional_base(in_place_init_if_t,bool cond,Args &&...args)389     explicit optional_base ( in_place_init_if_t, bool cond, Args&&... args )
390       :
391       m_initialized(false)
392     {
393       if ( cond )
394         construct(in_place_init, boost::forward<Args>(args)...);
395     }
396 #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
397     template<class Arg>
construct(in_place_init_t,Arg && arg)398     void construct ( in_place_init_t, Arg&& arg )
399      {
400        ::new (m_storage.address()) value_type( boost::forward<Arg>(arg) );
401        m_initialized = true ;
402      }
403 
construct(in_place_init_t)404     void construct ( in_place_init_t )
405      {
406        ::new (m_storage.address()) value_type();
407        m_initialized = true ;
408      }
409 
410     template<class Arg>
emplace_assign(Arg && arg)411     void emplace_assign ( Arg&& arg )
412      {
413        destroy();
414        construct(in_place_init, boost::forward<Arg>(arg)) ;
415      }
416 
emplace_assign()417     void emplace_assign ()
418      {
419        destroy();
420        construct(in_place_init) ;
421      }
422 
423     template<class Arg>
optional_base(in_place_init_t,Arg && arg)424     explicit optional_base ( in_place_init_t, Arg&& arg )
425       :
426       m_initialized(false)
427     {
428       construct(in_place_init, boost::forward<Arg>(arg));
429     }
430 
optional_base(in_place_init_t)431     explicit optional_base ( in_place_init_t )
432       :
433       m_initialized(false)
434     {
435       construct(in_place_init);
436     }
437 
438     template<class Arg>
optional_base(in_place_init_if_t,bool cond,Arg && arg)439     explicit optional_base ( in_place_init_if_t, bool cond, Arg&& arg )
440       :
441       m_initialized(false)
442     {
443       if ( cond )
444         construct(in_place_init, boost::forward<Arg>(arg));
445     }
446 
optional_base(in_place_init_if_t,bool cond)447     explicit optional_base ( in_place_init_if_t, bool cond )
448       :
449       m_initialized(false)
450     {
451       if ( cond )
452         construct(in_place_init);
453     }
454 
455 #else
456 
457     template<class Arg>
construct(in_place_init_t,const Arg & arg)458     void construct ( in_place_init_t, const Arg& arg )
459      {
460        ::new (m_storage.address()) value_type( arg );
461        m_initialized = true ;
462      }
463 
464     template<class Arg>
construct(in_place_init_t,Arg & arg)465     void construct ( in_place_init_t, Arg& arg )
466      {
467        ::new (m_storage.address()) value_type( arg );
468        m_initialized = true ;
469      }
470 
construct(in_place_init_t)471     void construct ( in_place_init_t )
472      {
473        ::new (m_storage.address()) value_type();
474        m_initialized = true ;
475      }
476 
477     template<class Arg>
emplace_assign(const Arg & arg)478     void emplace_assign ( const Arg& arg )
479     {
480       destroy();
481       construct(in_place_init, arg);
482     }
483 
484     template<class Arg>
emplace_assign(Arg & arg)485     void emplace_assign ( Arg& arg )
486     {
487       destroy();
488       construct(in_place_init, arg);
489     }
490 
emplace_assign()491     void emplace_assign ()
492     {
493       destroy();
494       construct(in_place_init);
495     }
496 
497     template<class Arg>
optional_base(in_place_init_t,const Arg & arg)498     explicit optional_base ( in_place_init_t, const Arg& arg )
499       : m_initialized(false)
500     {
501       construct(in_place_init, arg);
502     }
503 
504     template<class Arg>
optional_base(in_place_init_t,Arg & arg)505     explicit optional_base ( in_place_init_t, Arg& arg )
506       : m_initialized(false)
507     {
508       construct(in_place_init, arg);
509     }
510 
optional_base(in_place_init_t)511     explicit optional_base ( in_place_init_t )
512       : m_initialized(false)
513     {
514       construct(in_place_init);
515     }
516 
517     template<class Arg>
optional_base(in_place_init_if_t,bool cond,const Arg & arg)518     explicit optional_base ( in_place_init_if_t, bool cond, const Arg& arg )
519       : m_initialized(false)
520     {
521       if ( cond )
522         construct(in_place_init, arg);
523     }
524 
525     template<class Arg>
optional_base(in_place_init_if_t,bool cond,Arg & arg)526     explicit optional_base ( in_place_init_if_t, bool cond, Arg& arg )
527       : m_initialized(false)
528     {
529       if ( cond )
530         construct(in_place_init, arg);
531     }
532 
optional_base(in_place_init_if_t,bool cond)533     explicit optional_base ( in_place_init_if_t, bool cond )
534       : m_initialized(false)
535     {
536       if ( cond )
537         construct(in_place_init);
538     }
539 #endif
540 
541 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
542 
543 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
544     // Constructs in-place using the given factory
545     template<class Expr>
construct(Expr && factory,in_place_factory_base const *)546     void construct ( Expr&& factory, in_place_factory_base const* )
547      {
548        boost_optional_detail::construct<value_type>(factory, m_storage.address());
549        m_initialized = true ;
550      }
551 
552     // Constructs in-place using the given typed factory
553     template<class Expr>
construct(Expr && factory,typed_in_place_factory_base const *)554     void construct ( Expr&& factory, typed_in_place_factory_base const* )
555      {
556        factory.apply(m_storage.address()) ;
557        m_initialized = true ;
558      }
559 
560     template<class Expr>
assign_expr_to_initialized(Expr && factory,in_place_factory_base const * tag)561     void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag )
562      {
563        destroy();
564        construct(factory,tag);
565      }
566 
567     // Constructs in-place using the given typed factory
568     template<class Expr>
assign_expr_to_initialized(Expr && factory,typed_in_place_factory_base const * tag)569     void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag )
570      {
571        destroy();
572        construct(factory,tag);
573      }
574 
575 #else
576     // Constructs in-place using the given factory
577     template<class Expr>
construct(Expr const & factory,in_place_factory_base const *)578     void construct ( Expr const& factory, in_place_factory_base const* )
579      {
580        boost_optional_detail::construct<value_type>(factory, m_storage.address());
581        m_initialized = true ;
582      }
583 
584     // Constructs in-place using the given typed factory
585     template<class Expr>
construct(Expr const & factory,typed_in_place_factory_base const *)586     void construct ( Expr const& factory, typed_in_place_factory_base const* )
587      {
588        factory.apply(m_storage.address()) ;
589        m_initialized = true ;
590      }
591 
592     template<class Expr>
assign_expr_to_initialized(Expr const & factory,in_place_factory_base const * tag)593     void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag )
594      {
595        destroy();
596        construct(factory,tag);
597      }
598 
599     // Constructs in-place using the given typed factory
600     template<class Expr>
assign_expr_to_initialized(Expr const & factory,typed_in_place_factory_base const * tag)601     void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag )
602      {
603        destroy();
604        construct(factory,tag);
605      }
606 #endif
607 
608 #endif
609 
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.
615     template<class Expr>
construct(Expr && expr,void const *)616     void construct ( Expr&& expr, void const* )
617     {
618       new (m_storage.address()) value_type(boost::forward<Expr>(expr)) ;
619       m_initialized = true ;
620     }
621 
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.
626     template<class Expr>
assign_expr_to_initialized(Expr && expr,void const *)627     void assign_expr_to_initialized ( Expr&& expr, void const* )
628     {
629       assign_value( boost::forward<Expr>(expr) );
630     }
631 #else
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.
636     template<class Expr>
construct(Expr const & expr,void const *)637     void construct ( Expr const& expr, void const* )
638      {
639        new (m_storage.address()) value_type(expr) ;
640        m_initialized = true ;
641      }
642 
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.
647     template<class Expr>
assign_expr_to_initialized(Expr const & expr,void const *)648     void assign_expr_to_initialized ( Expr const& expr, void const* )
649      {
650        assign_value(expr);
651      }
652 
653 #endif
654 
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.
664     //
665     // For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error
666     // instead of choosing the wrong overload
667     //
668 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
669     // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
670     template<class Expr>
construct(Expr && expr,optional_tag const *)671     void construct ( Expr&& expr, optional_tag const* )
672      {
673        if ( expr.is_initialized() )
674        {
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 ;
679        }
680      }
681 #else
682     // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
683     template<class Expr>
construct(Expr const & expr,optional_tag const *)684     void construct ( Expr const& expr, optional_tag const* )
685      {
686        if ( expr.is_initialized() )
687        {
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 ;
692        }
693      }
694 #endif
695 #endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
696 
assign_value(argument_type val)697     void assign_value ( argument_type val ) { get_impl() = val; }
698 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
assign_value(rval_reference_type val)699     void assign_value ( rval_reference_type val ) { get_impl() = static_cast<rval_reference_type>(val); }
700 #endif
701 
destroy()702     void destroy()
703     {
704       if ( m_initialized )
705         destroy_impl() ;
706     }
707 
get_impl() const708     reference_const_type get_impl() const { return m_storage.ref() ; }
get_impl()709     reference_type       get_impl()       { return m_storage.ref() ; }
710 
get_ptr_impl() const711     pointer_const_type get_ptr_impl() const { return m_storage.ptr_ref(); }
get_ptr_impl()712     pointer_type       get_ptr_impl()       { return m_storage.ptr_ref(); }
713 
714   private :
715 
716 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1600)
destroy_impl()717     void destroy_impl ( ) { m_storage.ptr_ref()->~T() ; m_initialized = false ; }
718 #else
719     void destroy_impl ( ) { m_storage.ref().T::~T() ; m_initialized = false ; }
720 #endif
721 
722     bool m_initialized ;
723     storage_type m_storage ;
724 } ;
725 
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
734 {};
735 
736 #if !defined(BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT)
737 
738 template <typename T, typename U>
739 struct is_convertible_to_T_or_factory
740   : boost::conditional< boost::is_base_of<boost::in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
741                      || boost::is_base_of<boost::typed_in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
742                      || (boost::is_constructible<T, U&&>::value && !boost::is_same<T, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value)
743                       , boost::true_type, boost::false_type>::type
744 {};
745 
746 template <typename T, typename U>
747 struct is_optional_constructible : boost::is_constructible<T, U>
748 {};
749 
750 #else
751 
752 template <typename, typename>
753 struct is_convertible_to_T_or_factory : boost::true_type
754 {};
755 
756 template <typename T, typename U>
757 struct is_optional_constructible : boost::true_type
758 {};
759 
760 #endif // is_convertible condition
761 
762 template <typename T, typename U>
763 struct is_optional_val_init_candidate
764   : boost::conditional< !is_optional_related<U>::value && is_convertible_to_T_or_factory<T, U>::value
765                       , boost::true_type, boost::false_type>::type
766 {};
767 
768 } // namespace optional_detail
769 
770 template<class T>
771 class optional : public optional_detail::optional_base<T>
772 {
773     typedef optional_detail::optional_base<T> base ;
774 
775   public :
776 
777     typedef optional<T> this_type ;
778 
779     typedef BOOST_DEDUCED_TYPENAME base::value_type           value_type ;
780     typedef BOOST_DEDUCED_TYPENAME base::reference_type       reference_type ;
781     typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
782 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
783     typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type  rval_reference_type ;
784     typedef BOOST_DEDUCED_TYPENAME base::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ;
785 #endif
786     typedef BOOST_DEDUCED_TYPENAME base::pointer_type         pointer_type ;
787     typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type   pointer_const_type ;
788     typedef BOOST_DEDUCED_TYPENAME base::argument_type        argument_type ;
789 
790     // Creates an optional<T> uninitialized.
791     // No-throw
optional()792     optional() BOOST_NOEXCEPT : base() {}
793 
794     // Creates an optional<T> uninitialized.
795     // No-throw
optional(none_t none_)796     optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {}
797 
798     // Creates an optional<T> initialized with 'val'.
799     // Can throw if T::T(T const&) does
optional(argument_type val)800     optional ( argument_type val ) : base(val) {}
801 
802 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
803     // Creates an optional<T> initialized with 'move(val)'.
804     // Can throw if T::T(T &&) does
optional(rval_reference_type val)805     optional ( rval_reference_type val ) : base( boost::forward<T>(val) )
806       {}
807 #endif
808 
809     // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
810     // Can throw if T::T(T const&) does
optional(bool cond,argument_type val)811     optional ( bool cond, argument_type val ) : base(cond,val) {}
812 
813     // NOTE: MSVC needs templated versions first
814 
815     // Creates a deep copy of another convertible optional<U>
816     // Requires a valid conversion from U to T.
817     // Can throw if T::T(U const&) does
818     template<class U>
optional(optional<U> const & rhs,typename boost::enable_if<optional_detail::is_optional_constructible<T,U const &>>::type * =0)819     explicit optional ( optional<U> const& rhs
820 #ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS
821                         ,typename boost::enable_if< optional_detail::is_optional_constructible<T, U const&> >::type* = 0
822 #endif
823                       )
824       :
825       base()
826     {
827       if ( rhs.is_initialized() )
828         this->construct(rhs.get());
829     }
830 
831 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
832     // Creates a deep move of another convertible optional<U>
833     // Requires a valid conversion from U to T.
834     // Can throw if T::T(U&&) does
835     template<class U>
optional(optional<U> && rhs,typename boost::enable_if<optional_detail::is_optional_constructible<T,U>>::type * =0)836     explicit optional ( optional<U> && rhs
837 #ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS
838                         ,typename boost::enable_if< optional_detail::is_optional_constructible<T, U> >::type* = 0
839 #endif
840                       )
841       :
842       base()
843     {
844       if ( rhs.is_initialized() )
845         this->construct( boost::move(rhs.get()) );
846     }
847 #endif
848 
849 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
850     // Creates an optional<T> with an expression which can be either
851     //  (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
852     //  (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
853     //  (c) Any expression implicitly convertible to the single type
854     //      of a one-argument T's constructor.
855     //  (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
856     //       even though explicit overloads are present for these.
857     // Depending on the above some T ctor is called.
858     // Can throw if the resolved T ctor throws.
859 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
860 
861 
862   template<class Expr>
optional(Expr && expr,BOOST_DEDUCED_TYPENAME boost::enable_if<optional_detail::is_optional_val_init_candidate<T,Expr>>::type * =0)863   explicit optional ( Expr&& expr,
864                       BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_val_init_candidate<T, Expr> >::type* = 0
865   )
866     : base(boost::forward<Expr>(expr),boost::addressof(expr))
867     {}
868 
869 #else
870     template<class Expr>
optional(Expr const & expr)871     explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
872 #endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
873 #endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
874 
875     // Creates a deep copy of another optional<T>
876     // Can throw if T::T(T const&) does
optional(optional const & rhs)877     optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
878 
879 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
880 	// Creates a deep move of another optional<T>
881 	// Can throw if T::T(T&&) does
882 	optional ( optional && rhs )
BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)883 	  BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
884 	  : base( boost::move(rhs) )
885 	{}
886 
887 #endif
888 
889 #if BOOST_WORKAROUND(_MSC_VER, <= 1600)
890     //  On old MSVC compilers the implicitly declared dtor is not called
~optional()891     ~optional() {}
892 #endif
893 
894 
895 #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
896     // Assigns from an expression. See corresponding constructor.
897     // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
898 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
899 
900     template<class Expr>
901     BOOST_DEDUCED_TYPENAME boost::enable_if<optional_detail::is_optional_val_init_candidate<T, Expr>, optional&>::type
operator =(Expr && expr)902     operator= ( Expr&& expr )
903       {
904         this->assign_expr(boost::forward<Expr>(expr),boost::addressof(expr));
905         return *this ;
906       }
907 
908 #else
909     template<class Expr>
operator =(Expr const & expr)910     optional& operator= ( Expr const& expr )
911       {
912         this->assign_expr(expr,boost::addressof(expr));
913         return *this ;
914       }
915 #endif // !defined  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
916 #endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
917 
918     // Copy-assigns from another convertible optional<U> (converts && deep-copies the rhs value)
919     // Requires a valid conversion from U to T.
920     // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
921     template<class U>
operator =(optional<U> const & rhs)922     optional& operator= ( optional<U> const& rhs )
923       {
924         this->assign(rhs);
925         return *this ;
926       }
927 
928 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
929     // Move-assigns from another convertible optional<U> (converts && deep-moves the rhs value)
930     // Requires a valid conversion from U to T.
931     // Basic Guarantee: If T::T( U && ) throws, this is left UNINITIALIZED
932     template<class U>
operator =(optional<U> && rhs)933     optional& operator= ( optional<U> && rhs )
934       {
935         this->assign(boost::move(rhs));
936         return *this ;
937       }
938 #endif
939 
940     // Assigns from another optional<T> (deep-copies the rhs value)
941     // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
942     //  (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
operator =(optional const & rhs)943     optional& operator= ( optional const& rhs )
944       {
945         this->assign( static_cast<base const&>(rhs) ) ;
946         return *this ;
947       }
948 
949 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
950     // Assigns from another optional<T> (deep-moves the rhs value)
operator =(optional && rhs)951     optional& operator= ( optional && rhs )
952 	  BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
953       {
954         this->assign( static_cast<base &&>(rhs) ) ;
955         return *this ;
956       }
957 #endif
958 
959 #ifndef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
960 
961     // Assigns from a T (deep-moves/copies the rhs value)
962     template <typename T_>
963     BOOST_DEDUCED_TYPENAME boost::enable_if<boost::is_same<T, BOOST_DEDUCED_TYPENAME boost::decay<T_>::type>, optional&>::type
operator =(T_ && val)964     operator= ( T_&& val )
965       {
966         this->assign( boost::forward<T_>(val) ) ;
967         return *this ;
968       }
969 
970 #else
971 
972     // Assigns from a T (deep-copies the rhs value)
973     // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
operator =(argument_type val)974     optional& operator= ( argument_type val )
975       {
976         this->assign( val ) ;
977         return *this ;
978       }
979 
980 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
981     // Assigns from a T (deep-moves the rhs value)
operator =(rval_reference_type val)982     optional& operator= ( rval_reference_type val )
983       {
984         this->assign( boost::move(val) ) ;
985         return *this ;
986       }
987 #endif
988 
989 #endif // BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
990 
991     // Assigns from a "none"
992     // Which destroys the current value, if any, leaving this UNINITIALIZED
993     // No-throw (assuming T::~T() doesn't)
operator =(none_t none_)994     optional& operator= ( none_t none_ ) BOOST_NOEXCEPT
995       {
996         this->assign( none_ ) ;
997         return *this ;
998       }
999 
1000 #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1001     // Constructs in-place
1002     // upon exception *this is always uninitialized
1003     template<class... Args>
emplace(Args &&...args)1004     void emplace ( Args&&... args )
1005     {
1006       this->emplace_assign( boost::forward<Args>(args)... );
1007     }
1008 
1009     template<class... Args>
optional(in_place_init_t,Args &&...args)1010     explicit optional ( in_place_init_t, Args&&... args )
1011     : base( in_place_init, boost::forward<Args>(args)... )
1012     {}
1013 
1014     template<class... Args>
optional(in_place_init_if_t,bool cond,Args &&...args)1015     explicit optional ( in_place_init_if_t, bool cond, Args&&... args )
1016     : base( in_place_init_if, cond, boost::forward<Args>(args)... )
1017     {}
1018 
1019 #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
1020     template<class Arg>
emplace(Arg && arg)1021     void emplace ( Arg&& arg )
1022      {
1023        this->emplace_assign( boost::forward<Arg>(arg) );
1024      }
1025 
emplace()1026     void emplace ()
1027      {
1028        this->emplace_assign();
1029      }
1030 
1031     template<class Args>
optional(in_place_init_t,Args && args)1032     explicit optional ( in_place_init_t, Args&& args )
1033     : base( in_place_init, boost::forward<Args>(args) )
1034     {}
1035 
optional(in_place_init_t)1036     explicit optional ( in_place_init_t )
1037     : base( in_place_init )
1038     {}
1039 
1040     template<class Args>
optional(in_place_init_if_t,bool cond,Args && args)1041     explicit optional ( in_place_init_if_t, bool cond, Args&& args )
1042     : base( in_place_init_if, cond, boost::forward<Args>(args) )
1043     {}
1044 
optional(in_place_init_if_t,bool cond)1045     explicit optional ( in_place_init_if_t, bool cond )
1046     : base( in_place_init_if, cond )
1047     {}
1048 #else
1049     template<class Arg>
emplace(const Arg & arg)1050     void emplace ( const Arg& arg )
1051      {
1052        this->emplace_assign( arg );
1053      }
1054 
1055     template<class Arg>
emplace(Arg & arg)1056     void emplace ( Arg& arg )
1057      {
1058        this->emplace_assign( arg );
1059      }
1060 
emplace()1061     void emplace ()
1062      {
1063        this->emplace_assign();
1064      }
1065 
1066     template<class Arg>
optional(in_place_init_t,const Arg & arg)1067     explicit optional ( in_place_init_t, const Arg& arg )
1068     : base( in_place_init, arg )
1069     {}
1070 
1071     template<class Arg>
optional(in_place_init_t,Arg & arg)1072     explicit optional ( in_place_init_t, Arg& arg )
1073     : base( in_place_init, arg )
1074     {}
1075 
optional(in_place_init_t)1076     explicit optional ( in_place_init_t )
1077     : base( in_place_init )
1078     {}
1079 
1080     template<class Arg>
optional(in_place_init_if_t,bool cond,const Arg & arg)1081     explicit optional ( in_place_init_if_t, bool cond, const Arg& arg )
1082     : base( in_place_init_if, cond, arg )
1083     {}
1084 
1085     template<class Arg>
optional(in_place_init_if_t,bool cond,Arg & arg)1086     explicit optional ( in_place_init_if_t, bool cond, Arg& arg )
1087     : base( in_place_init_if, cond, arg )
1088     {}
1089 
optional(in_place_init_if_t,bool cond)1090     explicit optional ( in_place_init_if_t, bool cond )
1091     : base( in_place_init_if, cond )
1092     {}
1093 #endif
1094 
swap(optional & arg)1095     void swap( optional & arg )
1096 	  BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
1097       {
1098         // allow for Koenig lookup
1099         boost::swap(*this, arg);
1100       }
1101 
1102 
1103     // Returns a reference to the value if this is initialized, otherwise,
1104     // the behaviour is UNDEFINED
1105     // No-throw
get() const1106     reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
get()1107     reference_type       get()       { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
1108 
1109     // Returns a copy of the value if this is initialized, 'v' otherwise
get_value_or(reference_const_type v) const1110     reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
get_value_or(reference_type v)1111     reference_type       get_value_or ( reference_type       v )       { return this->is_initialized() ? get() : v ; }
1112 
1113     // Returns a pointer to the value if this is initialized, otherwise,
1114     // the behaviour is UNDEFINED
1115     // No-throw
operator ->() const1116     pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
operator ->()1117     pointer_type       operator->()       { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
1118 
1119     // Returns a reference to the value if this is initialized, otherwise,
1120     // the behaviour is UNDEFINED
1121     // No-throw
1122 #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
operator *() const1123     reference_const_type operator *() const& { return this->get() ; }
operator *()1124     reference_type       operator *() &      { return this->get() ; }
operator *()1125     reference_type_of_temporary_wrapper operator *() && { return boost::move(this->get()) ; }
1126 #else
operator *() const1127     reference_const_type operator *() const { return this->get() ; }
operator *()1128     reference_type       operator *()       { return this->get() ; }
1129 #endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS
1130 
1131 #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
value() const1132     reference_const_type value() const&
1133       {
1134         if (this->is_initialized())
1135           return this->get() ;
1136         else
1137           throw_exception(bad_optional_access());
1138       }
1139 
value()1140     reference_type value() &
1141       {
1142         if (this->is_initialized())
1143           return this->get() ;
1144         else
1145           throw_exception(bad_optional_access());
1146       }
1147 
value()1148     reference_type_of_temporary_wrapper value() &&
1149       {
1150         if (this->is_initialized())
1151           return boost::move(this->get()) ;
1152         else
1153           throw_exception(bad_optional_access());
1154       }
1155 
1156 #else
value() const1157     reference_const_type value() const
1158       {
1159         if (this->is_initialized())
1160           return this->get() ;
1161         else
1162           throw_exception(bad_optional_access());
1163       }
1164 
value()1165     reference_type value()
1166       {
1167         if (this->is_initialized())
1168           return this->get() ;
1169         else
1170           throw_exception(bad_optional_access());
1171       }
1172 #endif
1173 
1174 
1175 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
1176     template <class U>
value_or(U && v) const1177     value_type value_or ( U&& v ) const&
1178       {
1179         if (this->is_initialized())
1180           return get();
1181         else
1182           return boost::forward<U>(v);
1183       }
1184 
1185     template <class U>
value_or(U && v)1186     value_type value_or ( U&& v ) &&
1187       {
1188         if (this->is_initialized())
1189           return boost::move(get());
1190         else
1191           return boost::forward<U>(v);
1192       }
1193 #elif !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1194     template <class U>
value_or(U && v) const1195     value_type value_or ( U&& v ) const
1196       {
1197         if (this->is_initialized())
1198           return get();
1199         else
1200           return boost::forward<U>(v);
1201       }
1202 #else
1203     template <class U>
value_or(U const & v) const1204     value_type value_or ( U const& v ) const
1205       {
1206         if (this->is_initialized())
1207           return get();
1208         else
1209           return v;
1210       }
1211 
1212     template <class U>
value_or(U & v) const1213     value_type value_or ( U& v ) const
1214       {
1215         if (this->is_initialized())
1216           return get();
1217         else
1218           return v;
1219       }
1220 #endif
1221 
1222 
1223 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
1224     template <typename F>
value_or_eval(F f) const1225     value_type value_or_eval ( F f ) const&
1226       {
1227         if (this->is_initialized())
1228           return get();
1229         else
1230           return f();
1231       }
1232 
1233     template <typename F>
value_or_eval(F f)1234     value_type value_or_eval ( F f ) &&
1235       {
1236         if (this->is_initialized())
1237           return boost::move(get());
1238         else
1239           return f();
1240       }
1241 #else
1242     template <typename F>
value_or_eval(F f) const1243     value_type value_or_eval ( F f ) const
1244       {
1245         if (this->is_initialized())
1246           return get();
1247         else
1248           return f();
1249       }
1250 #endif
1251 
operator !() const1252     bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; }
1253 
1254     BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
1255 } ;
1256 
1257 } // namespace boost
1258 
1259 #endif // BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL
1260 
1261 namespace boost {
1262 
1263 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1264 template<class T>
1265 class optional<T&&>
1266 {
1267   BOOST_STATIC_ASSERT_MSG(sizeof(T) == 0, "Optional rvalue references are illegal.");
1268 } ;
1269 #endif
1270 
1271 } // namespace boost
1272 
1273 #ifndef BOOST_OPTIONAL_CONFIG_DONT_SPECIALIZE_OPTIONAL_REFS
1274 # include <boost/optional/detail/optional_reference_spec.hpp>
1275 #endif
1276 
1277 namespace boost {
1278 
1279 // Returns optional<T>(v)
1280 template<class T>
1281 inline
make_optional(T const & v)1282 optional<T> make_optional ( T const& v  )
1283 {
1284   return optional<T>(v);
1285 }
1286 
1287 // Returns optional<T>(cond,v)
1288 template<class T>
1289 inline
make_optional(bool cond,T const & v)1290 optional<T> make_optional ( bool cond, T const& v )
1291 {
1292   return optional<T>(cond,v);
1293 }
1294 
1295 // Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
1296 // No-throw
1297 template<class T>
1298 inline
1299 BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
get(optional<T> const & opt)1300 get ( optional<T> const& opt )
1301 {
1302   return opt.get() ;
1303 }
1304 
1305 template<class T>
1306 inline
1307 BOOST_DEDUCED_TYPENAME optional<T>::reference_type
get(optional<T> & opt)1308 get ( optional<T>& opt )
1309 {
1310   return opt.get() ;
1311 }
1312 
1313 // Returns a pointer to the value if this is initialized, otherwise, returns NULL.
1314 // No-throw
1315 template<class T>
1316 inline
1317 BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
get(optional<T> const * opt)1318 get ( optional<T> const* opt )
1319 {
1320   return opt->get_ptr() ;
1321 }
1322 
1323 template<class T>
1324 inline
1325 BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
get(optional<T> * opt)1326 get ( optional<T>* opt )
1327 {
1328   return opt->get_ptr() ;
1329 }
1330 
1331 // Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
1332 // No-throw
1333 template<class T>
1334 inline
1335 BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
get_optional_value_or(optional<T> const & opt,BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v)1336 get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v )
1337 {
1338   return opt.get_value_or(v) ;
1339 }
1340 
1341 template<class T>
1342 inline
1343 BOOST_DEDUCED_TYPENAME optional<T>::reference_type
get_optional_value_or(optional<T> & opt,BOOST_DEDUCED_TYPENAME optional<T>::reference_type v)1344 get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v )
1345 {
1346   return opt.get_value_or(v) ;
1347 }
1348 
1349 // Returns a pointer to the value if this is initialized, otherwise, returns NULL.
1350 // No-throw
1351 template<class T>
1352 inline
1353 BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
get_pointer(optional<T> const & opt)1354 get_pointer ( optional<T> const& opt )
1355 {
1356   return opt.get_ptr() ;
1357 }
1358 
1359 template<class T>
1360 inline
1361 BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
get_pointer(optional<T> & opt)1362 get_pointer ( optional<T>& opt )
1363 {
1364   return opt.get_ptr() ;
1365 }
1366 
1367 } // namespace boost
1368 
1369 namespace boost {
1370 
1371 // The following declaration prevents a bug where operator safe-bool is used upon streaming optional object if you forget the IO header.
1372 template<class CharType, class CharTrait>
1373 std::basic_ostream<CharType, CharTrait>&
operator <<(std::basic_ostream<CharType,CharTrait> & os,optional_detail::optional_tag const &)1374 operator<<(std::basic_ostream<CharType, CharTrait>& os, optional_detail::optional_tag const&)
1375 {
1376   BOOST_STATIC_ASSERT_MSG(sizeof(CharType) == 0, "If you want to output boost::optional, include header <boost/optional/optional_io.hpp>");
1377   return os;
1378 }
1379 
1380 } // namespace boost
1381 
1382 #include <boost/optional/detail/optional_relops.hpp>
1383 #include <boost/optional/detail/optional_swap.hpp>
1384 
1385 #endif // header guard
1386