]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/optional/include/boost/optional/optional.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / optional / include / boost / optional / optional.hpp
CommitLineData
7c673cae
FG
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_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40500) && !defined(__SUNPRO_CC)
737 // this condition is a copy paste from is_constructible.hpp
738 // I also disable SUNPRO, as it seems not to support type_traits correctly
739
740template <typename T, typename U>
741struct is_convertible_to_T_or_factory
742 : boost::conditional< boost::is_base_of<boost::in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
743 || boost::is_base_of<boost::typed_in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
744 || boost::is_constructible<T, U&&>::value
745 , boost::true_type, boost::false_type>::type
746{};
747
748#else
749
750#define BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT
751
752template <typename, typename>
753struct is_convertible_to_T_or_factory : boost::true_type
754{};
755
756#endif // is_convertible condition
757
758template <typename T, typename U>
759struct is_optional_val_init_candidate
760 : boost::conditional< !is_optional_related<U>::value && is_convertible_to_T_or_factory<T, U>::value
761 , boost::true_type, boost::false_type>::type
762{};
763
764} // namespace optional_detail
765
766template<class T>
767class optional : public optional_detail::optional_base<T>
768{
769 typedef optional_detail::optional_base<T> base ;
770
771 public :
772
773 typedef optional<T> this_type ;
774
775 typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ;
776 typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ;
777 typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
778#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
779 typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type rval_reference_type ;
780 typedef BOOST_DEDUCED_TYPENAME base::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ;
781#endif
782 typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ;
783 typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ;
784 typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
785
786 // Creates an optional<T> uninitialized.
787 // No-throw
788 optional() BOOST_NOEXCEPT : base() {}
789
790 // Creates an optional<T> uninitialized.
791 // No-throw
792 optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {}
793
794 // Creates an optional<T> initialized with 'val'.
795 // Can throw if T::T(T const&) does
796 optional ( argument_type val ) : base(val) {}
797
798#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
799 // Creates an optional<T> initialized with 'move(val)'.
800 // Can throw if T::T(T &&) does
801 optional ( rval_reference_type val ) : base( boost::forward<T>(val) )
802 {}
803#endif
804
805 // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
806 // Can throw if T::T(T const&) does
807 optional ( bool cond, argument_type val ) : base(cond,val) {}
808
809 // NOTE: MSVC needs templated versions first
810
811 // Creates a deep copy of another convertible optional<U>
812 // Requires a valid conversion from U to T.
813 // Can throw if T::T(U const&) does
814 template<class U>
815 explicit optional ( optional<U> const& rhs )
816 :
817 base()
818 {
819 if ( rhs.is_initialized() )
820 this->construct(rhs.get());
821 }
822
823#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
824 // Creates a deep move of another convertible optional<U>
825 // Requires a valid conversion from U to T.
826 // Can throw if T::T(U&&) does
827 template<class U>
828 explicit optional ( optional<U> && rhs )
829 :
830 base()
831 {
832 if ( rhs.is_initialized() )
833 this->construct( boost::move(rhs.get()) );
834 }
835#endif
836
837#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
838 // Creates an optional<T> with an expression which can be either
839 // (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
840 // (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
841 // (c) Any expression implicitly convertible to the single type
842 // of a one-argument T's constructor.
843 // (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
844 // even though explicit overloads are present for these.
845 // Depending on the above some T ctor is called.
846 // Can throw if the resolved T ctor throws.
847#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
848
849
850 template<class Expr>
851 explicit optional ( Expr&& expr,
852 BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_val_init_candidate<T, Expr> >::type* = 0
853 )
854 : base(boost::forward<Expr>(expr),boost::addressof(expr))
855 {}
856
857#else
858 template<class Expr>
859 explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
860#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
861#endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
862
863 // Creates a deep copy of another optional<T>
864 // Can throw if T::T(T const&) does
865 optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
866
867#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
868 // Creates a deep move of another optional<T>
869 // Can throw if T::T(T&&) does
870 optional ( optional && rhs )
871 BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
872 : base( boost::move(rhs) )
873 {}
874
875#endif
876
877#if BOOST_WORKAROUND(_MSC_VER, <= 1600)
878 // On old MSVC compilers the implicitly declared dtor is not called
879 ~optional() {}
880#endif
881
882
883#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
884 // Assigns from an expression. See corresponding constructor.
885 // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
886#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
887
888 template<class Expr>
889 BOOST_DEDUCED_TYPENAME boost::enable_if<optional_detail::is_optional_val_init_candidate<T, Expr>, optional&>::type
890 operator= ( Expr&& expr )
891 {
892 this->assign_expr(boost::forward<Expr>(expr),boost::addressof(expr));
893 return *this ;
894 }
895
896#else
897 template<class Expr>
898 optional& operator= ( Expr const& expr )
899 {
900 this->assign_expr(expr,boost::addressof(expr));
901 return *this ;
902 }
903#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
904#endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
905
906 // Copy-assigns from another convertible optional<U> (converts && deep-copies the rhs value)
907 // Requires a valid conversion from U to T.
908 // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
909 template<class U>
910 optional& operator= ( optional<U> const& rhs )
911 {
912 this->assign(rhs);
913 return *this ;
914 }
915
916#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
917 // Move-assigns from another convertible optional<U> (converts && deep-moves the rhs value)
918 // Requires a valid conversion from U to T.
919 // Basic Guarantee: If T::T( U && ) throws, this is left UNINITIALIZED
920 template<class U>
921 optional& operator= ( optional<U> && rhs )
922 {
923 this->assign(boost::move(rhs));
924 return *this ;
925 }
926#endif
927
928 // Assigns from another optional<T> (deep-copies the rhs value)
929 // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
930 // (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
931 optional& operator= ( optional const& rhs )
932 {
933 this->assign( static_cast<base const&>(rhs) ) ;
934 return *this ;
935 }
936
937#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
938 // Assigns from another optional<T> (deep-moves the rhs value)
939 optional& operator= ( optional && rhs )
940 BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
941 {
942 this->assign( static_cast<base &&>(rhs) ) ;
943 return *this ;
944 }
945#endif
946
947 // Assigns from a T (deep-copies the rhs value)
948 // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
949 optional& operator= ( argument_type val )
950 {
951 this->assign( val ) ;
952 return *this ;
953 }
954
955#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
956 // Assigns from a T (deep-moves the rhs value)
957 optional& operator= ( rval_reference_type val )
958 {
959 this->assign( boost::move(val) ) ;
960 return *this ;
961 }
962#endif
963
964 // Assigns from a "none"
965 // Which destroys the current value, if any, leaving this UNINITIALIZED
966 // No-throw (assuming T::~T() doesn't)
967 optional& operator= ( none_t none_ ) BOOST_NOEXCEPT
968 {
969 this->assign( none_ ) ;
970 return *this ;
971 }
972
973#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
974 // Constructs in-place
975 // upon exception *this is always uninitialized
976 template<class... Args>
977 void emplace ( Args&&... args )
978 {
979 this->emplace_assign( boost::forward<Args>(args)... );
980 }
981
982 template<class... Args>
983 explicit optional ( in_place_init_t, Args&&... args )
984 : base( in_place_init, boost::forward<Args>(args)... )
985 {}
986
987 template<class... Args>
988 explicit optional ( in_place_init_if_t, bool cond, Args&&... args )
989 : base( in_place_init_if, cond, boost::forward<Args>(args)... )
990 {}
991
992#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
993 template<class Arg>
994 void emplace ( Arg&& arg )
995 {
996 this->emplace_assign( boost::forward<Arg>(arg) );
997 }
998
999 void emplace ()
1000 {
1001 this->emplace_assign();
1002 }
1003
1004 template<class Args>
1005 explicit optional ( in_place_init_t, Args&& args )
1006 : base( in_place_init, boost::forward<Args>(args) )
1007 {}
1008
1009 explicit optional ( in_place_init_t )
1010 : base( in_place_init )
1011 {}
1012
1013 template<class Args>
1014 explicit optional ( in_place_init_if_t, bool cond, Args&& args )
1015 : base( in_place_init_if, cond, boost::forward<Args>(args) )
1016 {}
1017
1018 explicit optional ( in_place_init_if_t, bool cond )
1019 : base( in_place_init_if, cond )
1020 {}
1021#else
1022 template<class Arg>
1023 void emplace ( const Arg& arg )
1024 {
1025 this->emplace_assign( arg );
1026 }
1027
1028 template<class Arg>
1029 void emplace ( Arg& arg )
1030 {
1031 this->emplace_assign( arg );
1032 }
1033
1034 void emplace ()
1035 {
1036 this->emplace_assign();
1037 }
1038
1039 template<class Arg>
1040 explicit optional ( in_place_init_t, const Arg& arg )
1041 : base( in_place_init, arg )
1042 {}
1043
1044 template<class Arg>
1045 explicit optional ( in_place_init_t, Arg& arg )
1046 : base( in_place_init, arg )
1047 {}
1048
1049 explicit optional ( in_place_init_t )
1050 : base( in_place_init )
1051 {}
1052
1053 template<class Arg>
1054 explicit optional ( in_place_init_if_t, bool cond, const Arg& arg )
1055 : base( in_place_init_if, cond, arg )
1056 {}
1057
1058 template<class Arg>
1059 explicit optional ( in_place_init_if_t, bool cond, Arg& arg )
1060 : base( in_place_init_if, cond, arg )
1061 {}
1062
1063 explicit optional ( in_place_init_if_t, bool cond )
1064 : base( in_place_init_if, cond )
1065 {}
1066#endif
1067
1068 void swap( optional & arg )
1069 BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
1070 {
1071 // allow for Koenig lookup
1072 boost::swap(*this, arg);
1073 }
1074
1075
1076 // Returns a reference to the value if this is initialized, otherwise,
1077 // the behaviour is UNDEFINED
1078 // No-throw
1079 reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
1080 reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
1081
1082 // Returns a copy of the value if this is initialized, 'v' otherwise
1083 reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
1084 reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; }
1085
1086 // Returns a pointer to the value if this is initialized, otherwise,
1087 // the behaviour is UNDEFINED
1088 // No-throw
1089 pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
1090 pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
1091
1092 // Returns a reference to the value if this is initialized, otherwise,
1093 // the behaviour is UNDEFINED
1094 // No-throw
1095#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
1096 reference_const_type operator *() const& { return this->get() ; }
1097 reference_type operator *() & { return this->get() ; }
1098 reference_type_of_temporary_wrapper operator *() && { return boost::move(this->get()) ; }
1099#else
1100 reference_const_type operator *() const { return this->get() ; }
1101 reference_type operator *() { return this->get() ; }
1102#endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS
1103
1104#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
1105 reference_const_type value() const&
1106 {
1107 if (this->is_initialized())
1108 return this->get() ;
1109 else
1110 throw_exception(bad_optional_access());
1111 }
1112
1113 reference_type value() &
1114 {
1115 if (this->is_initialized())
1116 return this->get() ;
1117 else
1118 throw_exception(bad_optional_access());
1119 }
1120
1121 reference_type_of_temporary_wrapper value() &&
1122 {
1123 if (this->is_initialized())
1124 return boost::move(this->get()) ;
1125 else
1126 throw_exception(bad_optional_access());
1127 }
1128
1129#else
1130 reference_const_type value() const
1131 {
1132 if (this->is_initialized())
1133 return this->get() ;
1134 else
1135 throw_exception(bad_optional_access());
1136 }
1137
1138 reference_type value()
1139 {
1140 if (this->is_initialized())
1141 return this->get() ;
1142 else
1143 throw_exception(bad_optional_access());
1144 }
1145#endif
1146
1147
1148#ifndef BOOST_NO_CXX11_REF_QUALIFIERS
1149 template <class U>
1150 value_type value_or ( U&& v ) const&
1151 {
1152 if (this->is_initialized())
1153 return get();
1154 else
1155 return boost::forward<U>(v);
1156 }
1157
1158 template <class U>
1159 value_type value_or ( U&& v ) &&
1160 {
1161 if (this->is_initialized())
1162 return boost::move(get());
1163 else
1164 return boost::forward<U>(v);
1165 }
1166#elif !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1167 template <class U>
1168 value_type value_or ( U&& v ) const
1169 {
1170 if (this->is_initialized())
1171 return get();
1172 else
1173 return boost::forward<U>(v);
1174 }
1175#else
1176 template <class U>
1177 value_type value_or ( U const& v ) const
1178 {
1179 if (this->is_initialized())
1180 return get();
1181 else
1182 return v;
1183 }
1184
1185 template <class U>
1186 value_type value_or ( U& v ) const
1187 {
1188 if (this->is_initialized())
1189 return get();
1190 else
1191 return v;
1192 }
1193#endif
1194
1195
1196#ifndef BOOST_NO_CXX11_REF_QUALIFIERS
1197 template <typename F>
1198 value_type value_or_eval ( F f ) const&
1199 {
1200 if (this->is_initialized())
1201 return get();
1202 else
1203 return f();
1204 }
1205
1206 template <typename F>
1207 value_type value_or_eval ( F f ) &&
1208 {
1209 if (this->is_initialized())
1210 return boost::move(get());
1211 else
1212 return f();
1213 }
1214#else
1215 template <typename F>
1216 value_type value_or_eval ( F f ) const
1217 {
1218 if (this->is_initialized())
1219 return get();
1220 else
1221 return f();
1222 }
1223#endif
1224
1225 bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; }
1226
1227 BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
1228} ;
1229
1230} // namespace boost
1231
1232#endif // BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL
1233
1234namespace boost {
1235
1236#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1237template<class T>
1238class optional<T&&>
1239{
1240 BOOST_STATIC_ASSERT_MSG(sizeof(T) == 0, "Optional rvalue references are illegal.");
1241} ;
1242#endif
1243
1244} // namespace boost
1245
1246#ifndef BOOST_OPTIONAL_CONFIG_DONT_SPECIALIZE_OPTIONAL_REFS
1247# include <boost/optional/detail/optional_reference_spec.hpp>
1248#endif
1249
1250namespace boost {
1251
1252// Returns optional<T>(v)
1253template<class T>
1254inline
1255optional<T> make_optional ( T const& v )
1256{
1257 return optional<T>(v);
1258}
1259
1260// Returns optional<T>(cond,v)
1261template<class T>
1262inline
1263optional<T> make_optional ( bool cond, T const& v )
1264{
1265 return optional<T>(cond,v);
1266}
1267
1268// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
1269// No-throw
1270template<class T>
1271inline
1272BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
1273get ( optional<T> const& opt )
1274{
1275 return opt.get() ;
1276}
1277
1278template<class T>
1279inline
1280BOOST_DEDUCED_TYPENAME optional<T>::reference_type
1281get ( optional<T>& opt )
1282{
1283 return opt.get() ;
1284}
1285
1286// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
1287// No-throw
1288template<class T>
1289inline
1290BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
1291get ( optional<T> const* opt )
1292{
1293 return opt->get_ptr() ;
1294}
1295
1296template<class T>
1297inline
1298BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
1299get ( optional<T>* opt )
1300{
1301 return opt->get_ptr() ;
1302}
1303
1304// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
1305// No-throw
1306template<class T>
1307inline
1308BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
1309get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v )
1310{
1311 return opt.get_value_or(v) ;
1312}
1313
1314template<class T>
1315inline
1316BOOST_DEDUCED_TYPENAME optional<T>::reference_type
1317get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v )
1318{
1319 return opt.get_value_or(v) ;
1320}
1321
1322// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
1323// No-throw
1324template<class T>
1325inline
1326BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
1327get_pointer ( optional<T> const& opt )
1328{
1329 return opt.get_ptr() ;
1330}
1331
1332template<class T>
1333inline
1334BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
1335get_pointer ( optional<T>& opt )
1336{
1337 return opt.get_ptr() ;
1338}
1339
1340} // namespace boost
1341
1342namespace boost {
1343
1344// The following declaration prevents a bug where operator safe-bool is used upon streaming optional object if you forget the IO header.
1345template<class CharType, class CharTrait>
1346std::basic_ostream<CharType, CharTrait>&
1347operator<<(std::basic_ostream<CharType, CharTrait>& os, optional_detail::optional_tag const&)
1348{
1349 BOOST_STATIC_ASSERT_MSG(sizeof(CharType) == 0, "If you want to output boost::optional, include header <boost/optional/optional_io.hpp>");
1350 return os;
1351}
1352
1353} // namespace boost
1354
1355#include <boost/optional/detail/optional_relops.hpp>
1356#include <boost/optional/detail/optional_swap.hpp>
1357
1358#endif // header guard