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