1// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
2// Copyright (C) 2014 - 2021 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#ifndef BOOST_NO_IOSTREAM
22#include <iosfwd>
23#endif // BOOST_NO_IOSTREAM
24
25#ifdef BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS
26# include <type_traits>
27#endif
28
29#include <boost/assert.hpp>
30#include <boost/core/addressof.hpp>
31#include <boost/core/enable_if.hpp>
32#include <boost/core/explicit_operator_bool.hpp>
33#include <boost/core/swap.hpp>
34#include <boost/optional/bad_optional_access.hpp>
35#include <boost/static_assert.hpp>
36#include <boost/throw_exception.hpp>
37#include <boost/type.hpp>
38#include <boost/type_traits/alignment_of.hpp>
39#include <boost/type_traits/conditional.hpp>
40#include <boost/type_traits/conjunction.hpp>
41#include <boost/type_traits/disjunction.hpp>
42#include <boost/type_traits/has_nothrow_constructor.hpp>
43#include <boost/type_traits/type_with_alignment.hpp>
44#include <boost/type_traits/remove_const.hpp>
45#include <boost/type_traits/remove_reference.hpp>
46#include <boost/type_traits/decay.hpp>
47#include <boost/type_traits/is_assignable.hpp>
48#include <boost/type_traits/is_base_of.hpp>
49#include <boost/type_traits/is_const.hpp>
50#include <boost/type_traits/is_constructible.hpp>
51#include <boost/type_traits/is_convertible.hpp>
52#include <boost/type_traits/is_lvalue_reference.hpp>
53#include <boost/type_traits/is_nothrow_move_assignable.hpp>
54#include <boost/type_traits/is_nothrow_move_constructible.hpp>
55#include <boost/type_traits/is_rvalue_reference.hpp>
56#include <boost/type_traits/is_same.hpp>
57#include <boost/type_traits/is_volatile.hpp>
58#include <boost/type_traits/is_scalar.hpp>
59#include <boost/move/utility.hpp>
60#include <boost/none.hpp>
61#include <boost/utility/compare_pointees.hpp>
62#include <boost/utility/result_of.hpp>
63
64#include <boost/optional/optional_fwd.hpp>
65#include <boost/optional/detail/optional_config.hpp>
66#include <boost/optional/detail/optional_factory_support.hpp>
67#include <boost/optional/detail/optional_aligned_storage.hpp>
68#include <boost/optional/detail/optional_hash.hpp>
69
70namespace boost { namespace optional_detail {
71
72template <typename T>
73struct optional_value_type
74{
75};
76
77template <typename T>
78struct optional_value_type< ::boost::optional<T> >
79{
80 typedef T type;
81};
82
83}} // namespace boost::optional_detail
84
85#ifdef BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL
86#include <boost/optional/detail/old_optional_implementation.hpp>
87#else
88namespace boost {
89
90namespace optional_ns {
91
92// a tag for in-place initialization of contained value
93struct in_place_init_t
94{
95 struct init_tag{};
96 explicit in_place_init_t(init_tag){}
97};
98const in_place_init_t in_place_init ((in_place_init_t::init_tag()));
99
100// a tag for conditional in-place initialization of contained value
101struct in_place_init_if_t
102{
103 struct init_tag{};
104 explicit in_place_init_if_t(init_tag){}
105};
106const in_place_init_if_t in_place_init_if ((in_place_init_if_t::init_tag()));
107
108} // namespace optional_ns
109
110using optional_ns::in_place_init_t;
111using optional_ns::in_place_init;
112using optional_ns::in_place_init_if_t;
113using optional_ns::in_place_init_if;
114
115namespace optional_detail {
116
117struct init_value_tag {};
118
119struct optional_tag {};
120
121
122template<class T>
123class optional_base : public optional_tag
124{
125 private :
126
127 typedef aligned_storage<T> storage_type ;
128 typedef optional_base<T> this_type ;
129
130 protected :
131
132 typedef T value_type ;
133 typedef typename boost::remove_const<T>::type unqualified_value_type;
134
135 protected:
136 typedef T & reference_type ;
137 typedef T const& reference_const_type ;
138#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
139 typedef T && rval_reference_type ;
140 typedef T && reference_type_of_temporary_wrapper ;
141#endif
142 typedef T * pointer_type ;
143 typedef T const* pointer_const_type ;
144 typedef T const& argument_type ;
145
146 // Creates an optional<T> uninitialized.
147 // No-throw
148 optional_base()
149 :
150 m_initialized(false) {}
151
152 // Creates an optional<T> uninitialized.
153 // No-throw
154 optional_base ( none_t )
155 :
156 m_initialized(false) {}
157
158 // Creates an optional<T> initialized with 'val'.
159 // Can throw if T::T(T const&) does
160 optional_base ( init_value_tag, argument_type val )
161 :
162 m_initialized(false)
163 {
164 construct(val);
165 }
166
167#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
168 // move-construct an optional<T> initialized from an rvalue-ref to 'val'.
169 // Can throw if T::T(T&&) does
170 optional_base ( init_value_tag, rval_reference_type val )
171 :
172 m_initialized(false)
173 {
174 construct( boost::move(val) );
175 }
176#endif
177
178 // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional<T>.
179 // Can throw if T::T(T const&) does
180 optional_base ( bool cond, argument_type val )
181 :
182 m_initialized(false)
183 {
184 if ( cond )
185 construct(val);
186 }
187
188#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
189 // Creates an optional<T> initialized with 'move(val)' IFF cond is true, otherwise creates an uninitialized optional<T>.
190 // Can throw if T::T(T &&) does
191 optional_base ( bool cond, rval_reference_type val )
192 :
193 m_initialized(false)
194 {
195 if ( cond )
196 construct(boost::move(val));
197 }
198#endif
199
200 // Creates a deep copy of another optional<T>
201 // Can throw if T::T(T const&) does
202 optional_base ( optional_base const& rhs )
203 :
204 m_initialized(false)
205 {
206 if ( rhs.is_initialized() )
207 construct(rhs.get_impl());
208 }
209
210#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
211 // Creates a deep move of another optional<T>
212 // Can throw if T::T(T&&) does
213 optional_base ( optional_base&& rhs )
214 BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
215 :
216 m_initialized(false)
217 {
218 if ( rhs.is_initialized() )
219 construct( boost::move(rhs.get_impl()) );
220 }
221#endif
222
223#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
224
225 template<class Expr, class PtrExpr>
226 explicit optional_base ( Expr&& expr, PtrExpr const* tag )
227 :
228 m_initialized(false)
229 {
230 construct(boost::forward<Expr>(expr),tag);
231 }
232
233#else
234 // This is used for both converting and in-place constructions.
235 // Derived classes use the 'tag' to select the appropriate
236 // implementation (the correct 'construct()' overload)
237 template<class Expr>
238 explicit optional_base ( Expr const& expr, Expr const* tag )
239 :
240 m_initialized(false)
241 {
242 construct(expr,tag);
243 }
244
245#endif
246
247 optional_base& operator= ( optional_base const& rhs )
248 {
249 this->assign(rhs);
250 return *this;
251 }
252
253#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
254 optional_base& operator= ( optional_base && rhs )
255 BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
256 {
257 this->assign(static_cast<optional_base&&>(rhs));
258 return *this;
259 }
260#endif
261
262 // No-throw (assuming T::~T() doesn't)
263 ~optional_base() { destroy() ; }
264
265 // Assigns from another optional<T> (deep-copies the rhs value)
266 void assign ( optional_base const& rhs )
267 {
268 if (is_initialized())
269 {
270 if ( rhs.is_initialized() )
271 assign_value(rhs.get_impl());
272 else destroy();
273 }
274 else
275 {
276 if ( rhs.is_initialized() )
277 construct(rhs.get_impl());
278 }
279 }
280
281#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
282 // Assigns from another optional<T> (deep-moves the rhs value)
283 void assign ( optional_base&& rhs )
284 {
285 if (is_initialized())
286 {
287 if ( rhs.is_initialized() )
288 assign_value( boost::move(rhs.get_impl()) );
289 else destroy();
290 }
291 else
292 {
293 if ( rhs.is_initialized() )
294 construct(boost::move(rhs.get_impl()));
295 }
296 }
297#endif
298
299 // Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
300 template<class U>
301 void assign ( optional<U> const& rhs )
302 {
303 if (is_initialized())
304 {
305 if ( rhs.is_initialized() )
306#ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
307 assign_value( rhs.get() );
308#else
309 assign_value( static_cast<value_type>(rhs.get()) );
310#endif
311
312 else destroy();
313 }
314 else
315 {
316 if ( rhs.is_initialized() )
317#ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
318 construct(rhs.get());
319#else
320 construct(static_cast<value_type>(rhs.get()));
321#endif
322 }
323 }
324
325#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
326 // move-assigns from another _convertible_ optional<U> (deep-moves from the rhs value)
327 template<class U>
328 void assign ( optional<U>&& rhs )
329 {
330 typedef BOOST_DEDUCED_TYPENAME optional<U>::rval_reference_type ref_type;
331 if (is_initialized())
332 {
333 if ( rhs.is_initialized() )
334 assign_value( static_cast<ref_type>(rhs.get()) );
335 else destroy();
336 }
337 else
338 {
339 if ( rhs.is_initialized() )
340 construct(static_cast<ref_type>(rhs.get()));
341 }
342 }
343#endif
344
345 // Assigns from a T (deep-copies the rhs value)
346 void assign ( argument_type val )
347 {
348 if (is_initialized())
349 assign_value(val);
350 else construct(val);
351 }
352
353#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
354 // Assigns from a T (deep-moves the rhs value)
355 void assign ( rval_reference_type val )
356 {
357 if (is_initialized())
358 assign_value( boost::move(val) );
359 else construct( boost::move(val) );
360 }
361#endif
362
363 // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
364 // No-throw (assuming T::~T() doesn't)
365 void assign ( none_t ) BOOST_NOEXCEPT { destroy(); }
366
367#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
368
369#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
370 template<class Expr, class ExprPtr>
371 void assign_expr ( Expr&& expr, ExprPtr const* tag )
372 {
373 if (is_initialized())
374 assign_expr_to_initialized(boost::forward<Expr>(expr),tag);
375 else construct(boost::forward<Expr>(expr),tag);
376 }
377#else
378 template<class Expr>
379 void assign_expr ( Expr const& expr, Expr const* tag )
380 {
381 if (is_initialized())
382 assign_expr_to_initialized(expr,tag);
383 else construct(expr,tag);
384 }
385#endif
386
387#endif
388
389 public :
390
391 // Destroys the current value, if any, leaving this UNINITIALIZED
392 // No-throw (assuming T::~T() doesn't)
393 void reset() BOOST_NOEXCEPT { destroy(); }
394
395 // **DEPRECATED** Replaces the current value -if any- with 'val'
396 void reset ( argument_type val ) { assign(val); }
397
398 // Returns a pointer to the value if this is initialized, otherwise,
399 // returns NULL.
400 // No-throw
401 pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
402 pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; }
403
404 bool is_initialized() const BOOST_NOEXCEPT { return m_initialized ; }
405
406 protected :
407
408 void construct ( argument_type val )
409 {
410 ::new (m_storage.address()) unqualified_value_type(val) ;
411 m_initialized = true ;
412 }
413
414#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
415 void construct ( rval_reference_type val )
416 {
417 ::new (m_storage.address()) unqualified_value_type( boost::move(val) ) ;
418 m_initialized = true ;
419 }
420#endif
421
422
423#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
424 // Constructs in-place
425 // upon exception *this is always uninitialized
426 template<class... Args>
427 void construct ( in_place_init_t, Args&&... args )
428 {
429 ::new (m_storage.address()) unqualified_value_type( boost::forward<Args>(args)... ) ;
430 m_initialized = true ;
431 }
432
433 template<class... Args>
434 void emplace_assign ( Args&&... args )
435 {
436 destroy();
437 construct(in_place_init, boost::forward<Args>(args)...);
438 }
439
440 template<class... Args>
441 explicit optional_base ( in_place_init_t, Args&&... args )
442 :
443 m_initialized(false)
444 {
445 construct(in_place_init, boost::forward<Args>(args)...);
446 }
447
448 template<class... Args>
449 explicit optional_base ( in_place_init_if_t, bool cond, Args&&... args )
450 :
451 m_initialized(false)
452 {
453 if ( cond )
454 construct(in_place_init, boost::forward<Args>(args)...);
455 }
456#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
457 template<class Arg>
458 void construct ( in_place_init_t, Arg&& arg )
459 {
460 ::new (m_storage.address()) unqualified_value_type( boost::forward<Arg>(arg) );
461 m_initialized = true ;
462 }
463
464 void construct ( in_place_init_t )
465 {
466 ::new (m_storage.address()) unqualified_value_type();
467 m_initialized = true ;
468 }
469
470 template<class Arg>
471 void emplace_assign ( Arg&& arg )
472 {
473 destroy();
474 construct(in_place_init, boost::forward<Arg>(arg)) ;
475 }
476
477 void emplace_assign ()
478 {
479 destroy();
480 construct(in_place_init) ;
481 }
482
483 template<class Arg>
484 explicit optional_base ( in_place_init_t, Arg&& arg )
485 :
486 m_initialized(false)
487 {
488 construct(in_place_init, boost::forward<Arg>(arg));
489 }
490
491 explicit optional_base ( in_place_init_t )
492 :
493 m_initialized(false)
494 {
495 construct(in_place_init);
496 }
497
498 template<class Arg>
499 explicit optional_base ( in_place_init_if_t, bool cond, Arg&& arg )
500 :
501 m_initialized(false)
502 {
503 if ( cond )
504 construct(in_place_init, boost::forward<Arg>(arg));
505 }
506
507 explicit optional_base ( in_place_init_if_t, bool cond )
508 :
509 m_initialized(false)
510 {
511 if ( cond )
512 construct(in_place_init);
513 }
514
515#else
516
517 template<class Arg>
518 void construct ( in_place_init_t, const Arg& arg )
519 {
520 ::new (m_storage.address()) unqualified_value_type( arg );
521 m_initialized = true ;
522 }
523
524 template<class Arg>
525 void construct ( in_place_init_t, Arg& arg )
526 {
527 ::new (m_storage.address()) unqualified_value_type( arg );
528 m_initialized = true ;
529 }
530
531 void construct ( in_place_init_t )
532 {
533 ::new (m_storage.address()) unqualified_value_type();
534 m_initialized = true ;
535 }
536
537 template<class Arg>
538 void emplace_assign ( const Arg& arg )
539 {
540 destroy();
541 construct(in_place_init, arg);
542 }
543
544 template<class Arg>
545 void emplace_assign ( Arg& arg )
546 {
547 destroy();
548 construct(in_place_init, arg);
549 }
550
551 void emplace_assign ()
552 {
553 destroy();
554 construct(in_place_init);
555 }
556
557 template<class Arg>
558 explicit optional_base ( in_place_init_t, const Arg& arg )
559 : m_initialized(false)
560 {
561 construct(in_place_init, arg);
562 }
563
564 template<class Arg>
565 explicit optional_base ( in_place_init_t, Arg& arg )
566 : m_initialized(false)
567 {
568 construct(in_place_init, arg);
569 }
570
571 explicit optional_base ( in_place_init_t )
572 : m_initialized(false)
573 {
574 construct(in_place_init);
575 }
576
577 template<class Arg>
578 explicit optional_base ( in_place_init_if_t, bool cond, const Arg& arg )
579 : m_initialized(false)
580 {
581 if ( cond )
582 construct(in_place_init, arg);
583 }
584
585 template<class Arg>
586 explicit optional_base ( in_place_init_if_t, bool cond, Arg& arg )
587 : m_initialized(false)
588 {
589 if ( cond )
590 construct(in_place_init, arg);
591 }
592
593 explicit optional_base ( in_place_init_if_t, bool cond )
594 : m_initialized(false)
595 {
596 if ( cond )
597 construct(in_place_init);
598 }
599#endif
600
601#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
602
603#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
604 // Constructs in-place using the given factory
605 template<class Expr>
606 void construct ( Expr&& factory, in_place_factory_base const* )
607 {
608 boost_optional_detail::construct<value_type>(factory, m_storage.address());
609 m_initialized = true ;
610 }
611
612 // Constructs in-place using the given typed factory
613 template<class Expr>
614 void construct ( Expr&& factory, typed_in_place_factory_base const* )
615 {
616 factory.apply(m_storage.address()) ;
617 m_initialized = true ;
618 }
619
620 template<class Expr>
621 void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag )
622 {
623 destroy();
624 construct(factory,tag);
625 }
626
627 // Constructs in-place using the given typed factory
628 template<class Expr>
629 void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag )
630 {
631 destroy();
632 construct(factory,tag);
633 }
634
635#else
636 // Constructs in-place using the given factory
637 template<class Expr>
638 void construct ( Expr const& factory, in_place_factory_base const* )
639 {
640 boost_optional_detail::construct<value_type>(factory, m_storage.address());
641 m_initialized = true ;
642 }
643
644 // Constructs in-place using the given typed factory
645 template<class Expr>
646 void construct ( Expr const& factory, typed_in_place_factory_base const* )
647 {
648 factory.apply(m_storage.address()) ;
649 m_initialized = true ;
650 }
651
652 template<class Expr>
653 void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag )
654 {
655 destroy();
656 construct(factory,tag);
657 }
658
659 // Constructs in-place using the given typed factory
660 template<class Expr>
661 void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag )
662 {
663 destroy();
664 construct(factory,tag);
665 }
666#endif
667
668#endif
669
670#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
671 // Constructs using any expression implicitly convertible to the single argument
672 // of a one-argument T constructor.
673 // Converting constructions of optional<T> from optional<U> uses this function with
674 // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
675 template<class Expr>
676 void construct ( Expr&& expr, void const* )
677 {
678 new (m_storage.address()) unqualified_value_type(boost::forward<Expr>(expr)) ;
679 m_initialized = true ;
680 }
681
682 // Assigns using a form any expression implicitly convertible to the single argument
683 // of a T's assignment operator.
684 // Converting assignments of optional<T> from optional<U> uses this function with
685 // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
686 template<class Expr>
687 void assign_expr_to_initialized ( Expr&& expr, void const* )
688 {
689 assign_value( boost::forward<Expr>(expr) );
690 }
691#else
692 // Constructs using any expression implicitly convertible to the single argument
693 // of a one-argument T constructor.
694 // Converting constructions of optional<T> from optional<U> uses this function with
695 // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
696 template<class Expr>
697 void construct ( Expr const& expr, void const* )
698 {
699 new (m_storage.address()) unqualified_value_type(expr) ;
700 m_initialized = true ;
701 }
702
703 // Assigns using a form any expression implicitly convertible to the single argument
704 // of a T's assignment operator.
705 // Converting assignments of optional<T> from optional<U> uses this function with
706 // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
707 template<class Expr>
708 void assign_expr_to_initialized ( Expr const& expr, void const* )
709 {
710 assign_value(expr);
711 }
712
713#endif
714
715#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
716 // BCB5.64 (and probably lower versions) workaround.
717 // The in-place factories are supported by means of catch-all constructors
718 // and assignment operators (the functions are parameterized in terms of
719 // an arbitrary 'Expr' type)
720 // This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U>
721 // to the 'Expr'-taking functions even though explicit overloads are present for them.
722 // Thus, the following overload is needed to properly handle the case when the 'lhs'
723 // is another optional.
724 //
725 // For VC<=70 compilers this workaround doesn't work because the compiler issues and error
726 // instead of choosing the wrong overload
727 //
728#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
729 // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
730 template<class Expr>
731 void construct ( Expr&& expr, optional_tag const* )
732 {
733 if ( expr.is_initialized() )
734 {
735 // An exception can be thrown here.
736 // It it happens, THIS will be left uninitialized.
737 new (m_storage.address()) unqualified_value_type(boost::move(expr.get())) ;
738 m_initialized = true ;
739 }
740 }
741#else
742 // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
743 template<class Expr>
744 void construct ( Expr const& expr, optional_tag const* )
745 {
746 if ( expr.is_initialized() )
747 {
748 // An exception can be thrown here.
749 // It it happens, THIS will be left uninitialized.
750 new (m_storage.address()) unqualified_value_type(expr.get()) ;
751 m_initialized = true ;
752 }
753 }
754#endif
755#endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
756
757 void assign_value ( argument_type val ) { get_impl() = val; }
758#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
759 void assign_value ( rval_reference_type val ) { get_impl() = static_cast<rval_reference_type>(val); }
760#endif
761
762 void destroy()
763 {
764 if ( m_initialized )
765 destroy_impl() ;
766 }
767
768 reference_const_type get_impl() const { return m_storage.ref() ; }
769 reference_type get_impl() { return m_storage.ref() ; }
770
771 pointer_const_type get_ptr_impl() const { return m_storage.ptr_ref(); }
772 pointer_type get_ptr_impl() { return m_storage.ptr_ref(); }
773
774 private :
775
776#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1900))
777 void destroy_impl ( ) { m_storage.ptr_ref()->~T() ; m_initialized = false ; }
778#else
779 void destroy_impl ( ) { m_storage.ref().T::~T() ; m_initialized = false ; }
780#endif
781
782 bool m_initialized ;
783 storage_type m_storage ;
784} ;
785
786#include <boost/optional/detail/optional_trivially_copyable_base.hpp>
787
788// definition of metafunction is_optional_val_init_candidate
789template <typename U>
790struct is_optional_or_tag
791 : boost::conditional< boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
792 || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, none_t>::value
793 || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, in_place_init_t>::value
794 || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, in_place_init_if_t>::value,
795 boost::true_type, boost::false_type>::type
796{};
797
798template <typename T, typename U>
799struct has_dedicated_constructor
800 : boost::disjunction<is_optional_or_tag<U>, boost::is_same<T, BOOST_DEDUCED_TYPENAME boost::decay<U>::type> >
801{};
802
803template <typename U>
804struct is_in_place_factory
805 : boost::disjunction< boost::is_base_of<boost::in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>,
806 boost::is_base_of<boost::typed_in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type> >
807{};
808
809#if !defined(BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT)
810
811template <typename T, typename U>
812struct is_factory_or_constructible_to_T
813 : boost::disjunction< is_in_place_factory<U>, boost::is_constructible<T, U&&> >
814{};
815
816template <typename T, typename U>
817struct is_optional_constructible : boost::is_constructible<T, U>
818{};
819
820#else
821
822template <typename, typename>
823struct is_factory_or_constructible_to_T : boost::true_type
824{};
825
826template <typename T, typename U>
827struct is_optional_constructible : boost::true_type
828{};
829
830#endif // is_convertible condition
831
832#if !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800)
833// for is_assignable
834
835#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES)
836// On some initial rvalue reference implementations GCC does it in a strange way,
837// preferring perfect-forwarding constructor to implicit copy constructor.
838
839template <typename T, typename U>
840struct is_opt_assignable
841 : boost::conjunction<boost::is_convertible<U&&, T>, boost::is_assignable<T&, U&&> >
842{};
843
844#else
845
846template <typename T, typename U>
847struct is_opt_assignable
848 : boost::conjunction<boost::is_convertible<U, T>, boost::is_assignable<T&, U> >
849{};
850
851#endif
852
853#else
854
855template <typename T, typename U>
856struct is_opt_assignable : boost::is_convertible<U, T>
857{};
858
859#endif
860
861template <typename T, typename U>
862struct is_factory_or_opt_assignable_to_T
863 : boost::disjunction< is_in_place_factory<U>, is_opt_assignable<T, U> >
864{};
865
866template <typename T, typename U, bool = has_dedicated_constructor<T, U>::value>
867struct is_optional_val_init_candidate
868 : boost::false_type
869{};
870
871template <typename T, typename U>
872struct is_optional_val_init_candidate<T, U, false>
873 : is_factory_or_constructible_to_T<T, U>
874{};
875
876template <typename T, typename U, bool = has_dedicated_constructor<T, U>::value>
877struct is_optional_val_assign_candidate
878 : boost::false_type
879{};
880
881template <typename T, typename U>
882struct is_optional_val_assign_candidate<T, U, false>
883 : is_factory_or_opt_assignable_to_T<T, U>
884{};
885
886} // namespace optional_detail
887
888namespace optional_config {
889
890template <typename T>
891struct optional_uses_direct_storage_for
892 : boost::conditional<(boost::is_scalar<T>::value && !boost::is_const<T>::value && !boost::is_volatile<T>::value)
893 , boost::true_type, boost::false_type>::type
894{};
895
896} // namespace optional_config
897
898
899#ifndef BOOST_OPTIONAL_DETAIL_NO_DIRECT_STORAGE_SPEC
900# define BOOST_OPTIONAL_BASE_TYPE(T) boost::conditional< optional_config::optional_uses_direct_storage_for<T>::value, \
901 optional_detail::tc_optional_base<T>, \
902 optional_detail::optional_base<T> \
903 >::type
904#else
905# define BOOST_OPTIONAL_BASE_TYPE(T) optional_detail::optional_base<T>
906#endif
907
908template<class T>
909class optional
910 : public BOOST_OPTIONAL_BASE_TYPE(T)
911{
912 typedef typename BOOST_OPTIONAL_BASE_TYPE(T) base ;
913
914 public :
915
916 typedef optional<T> this_type ;
917
918 typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ;
919 typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ;
920 typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
921#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
922 typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type rval_reference_type ;
923 typedef BOOST_DEDUCED_TYPENAME base::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ;
924#endif
925 typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ;
926 typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ;
927 typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
928
929 // Creates an optional<T> uninitialized.
930 // No-throw
931 optional() BOOST_NOEXCEPT : base() {}
932
933 // Creates an optional<T> uninitialized.
934 // No-throw
935 optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {}
936
937 // Creates an optional<T> initialized with 'val'.
938 // Can throw if T::T(T const&) does
939 optional ( argument_type val ) : base(optional_detail::init_value_tag(), val) {}
940
941#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
942 // Creates an optional<T> initialized with 'move(val)'.
943 // Can throw if T::T(T &&) does
944 optional ( rval_reference_type val ) : base(optional_detail::init_value_tag(), boost::forward<T>(val))
945 {}
946#endif
947
948 // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
949 // Can throw if T::T(T const&) does
950 optional ( bool cond, argument_type val ) : base(cond,val) {}
951
952#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
953 /// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
954 // Can throw if T::T(T &&) does
955 optional ( bool cond, rval_reference_type val ) : base( cond, boost::forward<T>(val) )
956 {}
957#endif
958
959 // NOTE: MSVC needs templated versions first
960
961 // Creates a deep copy of another convertible optional<U>
962 // Requires a valid conversion from U to T.
963 // Can throw if T::T(U const&) does
964 template<class U>
965 explicit optional ( optional<U> const& rhs
966#ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS
967 ,BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_constructible<T, U const&>, bool>::type = true
968#endif
969 )
970 :
971 base()
972 {
973 if ( rhs.is_initialized() )
974 this->construct(rhs.get());
975 }
976
977#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
978 // Creates a deep move of another convertible optional<U>
979 // Requires a valid conversion from U to T.
980 // Can throw if T::T(U&&) does
981 template<class U>
982 explicit optional ( optional<U> && rhs
983#ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS
984 ,BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_constructible<T, U>, bool>::type = true
985#endif
986 )
987 :
988 base()
989 {
990 if ( rhs.is_initialized() )
991 this->construct( boost::move(rhs.get()) );
992 }
993#endif
994
995#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
996 // Creates an optional<T> with an expression which can be either
997 // (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
998 // (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
999 // (c) Any expression implicitly convertible to the single type
1000 // of a one-argument T's constructor.
1001 // (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
1002 // even though explicit overloads are present for these.
1003 // Depending on the above some T ctor is called.
1004 // Can throw if the resolved T ctor throws.
1005#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1006
1007
1008 template<class Expr>
1009 explicit optional ( Expr&& expr,
1010 BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_val_init_candidate<T, Expr>, bool>::type = true
1011 )
1012 : base(boost::forward<Expr>(expr),boost::addressof(expr))
1013 {}
1014
1015#else
1016 template<class Expr>
1017 explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
1018#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1019#endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
1020
1021 // Creates a deep copy of another optional<T>
1022 // Can throw if T::T(T const&) does
1023#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
1024 optional ( optional const& ) = default;
1025#else
1026 optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
1027#endif
1028
1029#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1030 // Creates a deep move of another optional<T>
1031 // Can throw if T::T(T&&) does
1032
1033#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
1034 optional ( optional && ) = default;
1035#else
1036 optional ( optional && rhs )
1037 BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
1038 : base( boost::move(rhs) )
1039 {}
1040#endif
1041
1042#endif
1043
1044#if BOOST_WORKAROUND(_MSC_VER, <= 1600)
1045 // On old MSVC compilers the implicitly declared dtor is not called
1046 ~optional() {}
1047#endif
1048
1049
1050#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
1051 // Assigns from an expression. See corresponding constructor.
1052 // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
1053#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1054
1055 template<class Expr>
1056 BOOST_DEDUCED_TYPENAME boost::enable_if<optional_detail::is_optional_val_assign_candidate<T, Expr>, optional&>::type
1057 operator= ( Expr&& expr )
1058 {
1059 this->assign_expr(boost::forward<Expr>(expr),boost::addressof(expr));
1060 return *this ;
1061 }
1062
1063#else
1064 template<class Expr>
1065 optional& operator= ( Expr const& expr )
1066 {
1067 this->assign_expr(expr,boost::addressof(expr));
1068 return *this ;
1069 }
1070#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1071#endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
1072
1073 // Copy-assigns from another convertible optional<U> (converts && deep-copies the rhs value)
1074 // Requires a valid conversion from U to T.
1075 // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
1076 template<class U>
1077 optional& operator= ( optional<U> const& rhs )
1078 {
1079 this->assign(rhs);
1080 return *this ;
1081 }
1082
1083#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1084 // Move-assigns from another convertible optional<U> (converts && deep-moves the rhs value)
1085 // Requires a valid conversion from U to T.
1086 // Basic Guarantee: If T::T( U && ) throws, this is left UNINITIALIZED
1087 template<class U>
1088 optional& operator= ( optional<U> && rhs )
1089 {
1090 this->assign(boost::move(rhs));
1091 return *this ;
1092 }
1093#endif
1094
1095 // Assigns from another optional<T> (deep-copies the rhs value)
1096 // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
1097 // (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
1098#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
1099 optional& operator= ( optional const& rhs ) = default;
1100#else
1101 optional& operator= ( optional const& rhs )
1102 {
1103 this->assign( static_cast<base const&>(rhs) ) ;
1104 return *this ;
1105 }
1106#endif
1107
1108#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1109 // Assigns from another optional<T> (deep-moves the rhs value)
1110#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
1111 optional& operator= ( optional && ) = default;
1112#else
1113 optional& operator= ( optional && rhs )
1114 BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
1115 {
1116 this->assign( static_cast<base &&>(rhs) ) ;
1117 return *this ;
1118 }
1119#endif
1120
1121#endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1122
1123#ifndef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
1124
1125 // Assigns from a T (deep-moves/copies the rhs value)
1126 template <typename T_>
1127 BOOST_DEDUCED_TYPENAME boost::enable_if<boost::is_same<T, BOOST_DEDUCED_TYPENAME boost::decay<T_>::type>, optional&>::type
1128 operator= ( T_&& val )
1129 {
1130 this->assign( boost::forward<T_>(val) ) ;
1131 return *this ;
1132 }
1133
1134#else
1135
1136 // Assigns from a T (deep-copies the rhs value)
1137 // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
1138 optional& operator= ( argument_type val )
1139 {
1140 this->assign( val ) ;
1141 return *this ;
1142 }
1143
1144#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1145 // Assigns from a T (deep-moves the rhs value)
1146 optional& operator= ( rval_reference_type val )
1147 {
1148 this->assign( boost::move(val) ) ;
1149 return *this ;
1150 }
1151#endif
1152
1153#endif // BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
1154
1155 // Assigns from a "none"
1156 // Which destroys the current value, if any, leaving this UNINITIALIZED
1157 // No-throw (assuming T::~T() doesn't)
1158 optional& operator= ( none_t none_ ) BOOST_NOEXCEPT
1159 {
1160 this->assign( none_ ) ;
1161 return *this ;
1162 }
1163
1164#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1165 // Constructs in-place
1166 // upon exception *this is always uninitialized
1167 template<class... Args>
1168 void emplace ( Args&&... args )
1169 {
1170 this->emplace_assign( boost::forward<Args>(args)... );
1171 }
1172
1173 template<class... Args>
1174 explicit optional ( in_place_init_t, Args&&... args )
1175 : base( in_place_init, boost::forward<Args>(args)... )
1176 {}
1177
1178 template<class... Args>
1179 explicit optional ( in_place_init_if_t, bool cond, Args&&... args )
1180 : base( in_place_init_if, cond, boost::forward<Args>(args)... )
1181 {}
1182
1183#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
1184 template<class Arg>
1185 void emplace ( Arg&& arg )
1186 {
1187 this->emplace_assign( boost::forward<Arg>(arg) );
1188 }
1189
1190 void emplace ()
1191 {
1192 this->emplace_assign();
1193 }
1194
1195 template<class Args>
1196 explicit optional ( in_place_init_t, Args&& args )
1197 : base( in_place_init, boost::forward<Args>(args) )
1198 {}
1199
1200 explicit optional ( in_place_init_t )
1201 : base( in_place_init )
1202 {}
1203
1204 template<class Args>
1205 explicit optional ( in_place_init_if_t, bool cond, Args&& args )
1206 : base( in_place_init_if, cond, boost::forward<Args>(args) )
1207 {}
1208
1209 explicit optional ( in_place_init_if_t, bool cond )
1210 : base( in_place_init_if, cond )
1211 {}
1212#else
1213 template<class Arg>
1214 void emplace ( const Arg& arg )
1215 {
1216 this->emplace_assign( arg );
1217 }
1218
1219 template<class Arg>
1220 void emplace ( Arg& arg )
1221 {
1222 this->emplace_assign( arg );
1223 }
1224
1225 void emplace ()
1226 {
1227 this->emplace_assign();
1228 }
1229
1230 template<class Arg>
1231 explicit optional ( in_place_init_t, const Arg& arg )
1232 : base( in_place_init, arg )
1233 {}
1234
1235 template<class Arg>
1236 explicit optional ( in_place_init_t, Arg& arg )
1237 : base( in_place_init, arg )
1238 {}
1239
1240 explicit optional ( in_place_init_t )
1241 : base( in_place_init )
1242 {}
1243
1244 template<class Arg>
1245 explicit optional ( in_place_init_if_t, bool cond, const Arg& arg )
1246 : base( in_place_init_if, cond, arg )
1247 {}
1248
1249 template<class Arg>
1250 explicit optional ( in_place_init_if_t, bool cond, Arg& arg )
1251 : base( in_place_init_if, cond, arg )
1252 {}
1253
1254 explicit optional ( in_place_init_if_t, bool cond )
1255 : base( in_place_init_if, cond )
1256 {}
1257#endif
1258
1259 void swap( optional & arg )
1260 BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
1261 {
1262 // allow for Koenig lookup
1263 boost::swap(*this, arg);
1264 }
1265
1266
1267 // Returns a reference to the value if this is initialized, otherwise,
1268 // the behaviour is UNDEFINED
1269 // No-throw
1270 reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
1271 reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
1272
1273 // Returns a copy of the value if this is initialized, 'v' otherwise
1274 reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
1275 reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; }
1276
1277 // Returns a pointer to the value if this is initialized, otherwise,
1278 // the behaviour is UNDEFINED
1279 // No-throw
1280 pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
1281 pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
1282
1283 // Returns a reference to the value if this is initialized, otherwise,
1284 // the behaviour is UNDEFINED
1285 // No-throw
1286#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
1287 reference_const_type operator *() const& { return this->get() ; }
1288 reference_type operator *() & { return this->get() ; }
1289 reference_type_of_temporary_wrapper operator *() && { return boost::move(this->get()) ; }
1290#else
1291 reference_const_type operator *() const { return this->get() ; }
1292 reference_type operator *() { return this->get() ; }
1293#endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS
1294
1295#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
1296 reference_const_type value() const&
1297 {
1298 if (this->is_initialized())
1299 return this->get() ;
1300 else
1301 throw_exception(e: bad_optional_access());
1302 }
1303
1304 reference_type value() &
1305 {
1306 if (this->is_initialized())
1307 return this->get() ;
1308 else
1309 throw_exception(e: bad_optional_access());
1310 }
1311
1312 reference_type_of_temporary_wrapper value() &&
1313 {
1314 if (this->is_initialized())
1315 return boost::move(this->get()) ;
1316 else
1317 throw_exception(e: bad_optional_access());
1318 }
1319
1320#else
1321 reference_const_type value() const
1322 {
1323 if (this->is_initialized())
1324 return this->get() ;
1325 else
1326 throw_exception(bad_optional_access());
1327 }
1328
1329 reference_type value()
1330 {
1331 if (this->is_initialized())
1332 return this->get() ;
1333 else
1334 throw_exception(bad_optional_access());
1335 }
1336#endif
1337
1338
1339#ifndef BOOST_NO_CXX11_REF_QUALIFIERS
1340 template <class U>
1341 value_type value_or ( U&& v ) const&
1342 {
1343 if (this->is_initialized())
1344 return get();
1345 else
1346 return boost::forward<U>(v);
1347 }
1348
1349 template <class U>
1350 value_type value_or ( U&& v ) &&
1351 {
1352 if (this->is_initialized())
1353 return boost::move(get());
1354 else
1355 return boost::forward<U>(v);
1356 }
1357#elif !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1358 template <class U>
1359 value_type value_or ( U&& v ) const
1360 {
1361 if (this->is_initialized())
1362 return get();
1363 else
1364 return boost::forward<U>(v);
1365 }
1366#else
1367 template <class U>
1368 value_type value_or ( U const& v ) const
1369 {
1370 if (this->is_initialized())
1371 return get();
1372 else
1373 return v;
1374 }
1375
1376 template <class U>
1377 value_type value_or ( U& v ) const
1378 {
1379 if (this->is_initialized())
1380 return get();
1381 else
1382 return v;
1383 }
1384#endif
1385
1386
1387#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
1388 template <typename F>
1389 value_type value_or_eval ( F f ) const&
1390 {
1391 if (this->is_initialized())
1392 return get();
1393 else
1394 return f();
1395 }
1396
1397 template <typename F>
1398 value_type value_or_eval ( F f ) &&
1399 {
1400 if (this->is_initialized())
1401 return boost::move(get());
1402 else
1403 return f();
1404 }
1405
1406 template <typename F>
1407 optional<typename boost::result_of<F(reference_type)>::type> map(F f) &
1408 {
1409 if (this->has_value())
1410 return f(get());
1411 else
1412 return none;
1413 }
1414
1415 template <typename F>
1416 optional<typename boost::result_of<F(reference_const_type)>::type> map(F f) const&
1417 {
1418 if (this->has_value())
1419 return f(get());
1420 else
1421 return none;
1422 }
1423
1424 template <typename F>
1425 optional<typename boost::result_of<F(reference_type_of_temporary_wrapper)>::type> map(F f) &&
1426 {
1427 if (this->has_value())
1428 return f(boost::move(this->get()));
1429 else
1430 return none;
1431 }
1432
1433 template <typename F>
1434 optional<typename optional_detail::optional_value_type<typename boost::result_of<F(reference_type)>::type>::type> flat_map(F f) &
1435 {
1436 if (this->has_value())
1437 return f(get());
1438 else
1439 return none;
1440 }
1441
1442 template <typename F>
1443 optional<typename optional_detail::optional_value_type<typename boost::result_of<F(reference_const_type)>::type>::type> flat_map(F f) const&
1444 {
1445 if (this->has_value())
1446 return f(get());
1447 else
1448 return none;
1449 }
1450
1451 template <typename F>
1452 optional<typename optional_detail::optional_value_type<typename boost::result_of<F(reference_type_of_temporary_wrapper)>::type>::type> flat_map(F f) &&
1453 {
1454 if (this->has_value())
1455 return f(boost::move(get()));
1456 else
1457 return none;
1458 }
1459
1460#else
1461 template <typename F>
1462 value_type value_or_eval ( F f ) const
1463 {
1464 if (this->is_initialized())
1465 return get();
1466 else
1467 return f();
1468 }
1469
1470 template <typename F>
1471 optional<typename boost::result_of<F(reference_type)>::type> map(F f)
1472 {
1473 if (this->has_value())
1474 return f(get());
1475 else
1476 return none;
1477 }
1478
1479 template <typename F>
1480 optional<typename boost::result_of<F(reference_const_type)>::type> map(F f) const
1481 {
1482 if (this->has_value())
1483 return f(get());
1484 else
1485 return none;
1486 }
1487
1488 template <typename F>
1489 optional<typename optional_detail::optional_value_type<typename boost::result_of<F(reference_type)>::type>::type> flat_map(F f)
1490 {
1491 if (this->has_value())
1492 return f(get());
1493 else
1494 return none;
1495 }
1496
1497 template <typename F>
1498 optional<typename optional_detail::optional_value_type<typename boost::result_of<F(reference_const_type)>::type>::type> flat_map(F f) const
1499 {
1500 if (this->has_value())
1501 return f(get());
1502 else
1503 return none;
1504 }
1505
1506#endif
1507
1508 bool has_value() const BOOST_NOEXCEPT { return this->is_initialized() ; }
1509
1510 bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; }
1511
1512 BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
1513} ;
1514
1515} // namespace boost
1516
1517#endif // BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL
1518
1519namespace boost {
1520
1521#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1522template<class T>
1523class optional<T&&>
1524{
1525 BOOST_STATIC_ASSERT_MSG(sizeof(T) == 0, "Optional rvalue references are illegal.");
1526} ;
1527#endif
1528
1529} // namespace boost
1530
1531#ifndef BOOST_OPTIONAL_CONFIG_DONT_SPECIALIZE_OPTIONAL_REFS
1532# include <boost/optional/detail/optional_reference_spec.hpp>
1533#endif
1534
1535namespace boost {
1536
1537#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1538
1539template<class T>
1540inline
1541optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type> make_optional ( T && v )
1542{
1543 return optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type>(boost::forward<T>(v));
1544}
1545
1546// Returns optional<T>(cond,v)
1547template<class T>
1548inline
1549optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type> make_optional ( bool cond, T && v )
1550{
1551 return optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type>(cond,boost::forward<T>(v));
1552}
1553
1554#else
1555
1556// Returns optional<T>(v)
1557template<class T>
1558inline
1559optional<T> make_optional ( T const& v )
1560{
1561 return optional<T>(v);
1562}
1563
1564// Returns optional<T>(cond,v)
1565template<class T>
1566inline
1567optional<T> make_optional ( bool cond, T const& v )
1568{
1569 return optional<T>(cond,v);
1570}
1571
1572#endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1573
1574// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
1575// No-throw
1576template<class T>
1577inline
1578BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
1579get ( optional<T> const& opt )
1580{
1581 return opt.get() ;
1582}
1583
1584template<class T>
1585inline
1586BOOST_DEDUCED_TYPENAME optional<T>::reference_type
1587get ( optional<T>& opt )
1588{
1589 return opt.get() ;
1590}
1591
1592// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
1593// No-throw
1594template<class T>
1595inline
1596BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
1597get ( optional<T> const* opt )
1598{
1599 return opt->get_ptr() ;
1600}
1601
1602template<class T>
1603inline
1604BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
1605get ( optional<T>* opt )
1606{
1607 return opt->get_ptr() ;
1608}
1609
1610// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
1611// No-throw
1612template<class T>
1613inline
1614BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
1615get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v )
1616{
1617 return opt.get_value_or(v) ;
1618}
1619
1620template<class T>
1621inline
1622BOOST_DEDUCED_TYPENAME optional<T>::reference_type
1623get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v )
1624{
1625 return opt.get_value_or(v) ;
1626}
1627
1628// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
1629// No-throw
1630template<class T>
1631inline
1632BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
1633get_pointer ( optional<T> const& opt )
1634{
1635 return opt.get_ptr() ;
1636}
1637
1638template<class T>
1639inline
1640BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
1641get_pointer ( optional<T>& opt )
1642{
1643 return opt.get_ptr() ;
1644}
1645
1646} // namespace boost
1647
1648#ifndef BOOST_NO_IOSTREAM
1649namespace boost {
1650
1651// The following declaration prevents a bug where operator safe-bool is used upon streaming optional object if you forget the IO header.
1652template<class CharType, class CharTrait>
1653std::basic_ostream<CharType, CharTrait>&
1654operator<<(std::basic_ostream<CharType, CharTrait>& os, optional_detail::optional_tag const&)
1655{
1656 BOOST_STATIC_ASSERT_MSG(sizeof(CharType) == 0, "If you want to output boost::optional, include header <boost/optional/optional_io.hpp>");
1657 return os;
1658}
1659
1660} // namespace boost
1661#endif // BOOST_NO_IOSTREAM
1662
1663#include <boost/optional/detail/optional_relops.hpp>
1664#include <boost/optional/detail/optional_swap.hpp>
1665
1666#endif // header guard
1667