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