]> git.proxmox.com Git - ceph.git/blob - 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
1 // Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
2 // Copyright (C) 2014 - 2016 Andrzej Krzemienski.
3 //
4 // Use, modification, and distribution is subject to the Boost Software
5 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // See http://www.boost.org/libs/optional for documentation.
9 //
10 // You are welcome to contact the author at:
11 // fernando_cacciola@hotmail.com
12 //
13 // Revisions:
14 // 27 Apr 2008 (improved swap) Fernando Cacciola, Niels Dekker, Thorsten Ottosen
15 // 05 May 2014 (Added move semantics) Andrzej Krzemienski
16 //
17 #ifndef BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
18 #define BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
19
20 #include <new>
21 #include <iosfwd>
22
23 #include <boost/assert.hpp>
24 #include <boost/core/addressof.hpp>
25 #include <boost/core/enable_if.hpp>
26 #include <boost/core/explicit_operator_bool.hpp>
27 #include <boost/core/swap.hpp>
28 #include <boost/optional/bad_optional_access.hpp>
29 #include <boost/static_assert.hpp>
30 #include <boost/throw_exception.hpp>
31 #include <boost/type.hpp>
32 #include <boost/type_traits/alignment_of.hpp>
33 #include <boost/type_traits/conditional.hpp>
34 #include <boost/type_traits/has_nothrow_constructor.hpp>
35 #include <boost/type_traits/type_with_alignment.hpp>
36 #include <boost/type_traits/remove_const.hpp>
37 #include <boost/type_traits/remove_reference.hpp>
38 #include <boost/type_traits/decay.hpp>
39 #include <boost/type_traits/is_base_of.hpp>
40 #include <boost/type_traits/is_constructible.hpp>
41 #include <boost/type_traits/is_lvalue_reference.hpp>
42 #include <boost/type_traits/is_nothrow_move_assignable.hpp>
43 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
44 #include <boost/type_traits/is_rvalue_reference.hpp>
45 #include <boost/type_traits/is_same.hpp>
46 #include <boost/move/utility.hpp>
47 #include <boost/none.hpp>
48 #include <boost/utility/compare_pointees.hpp>
49
50 #include <boost/optional/optional_fwd.hpp>
51 #include <boost/optional/detail/optional_config.hpp>
52 #include <boost/optional/detail/optional_factory_support.hpp>
53 #include <boost/optional/detail/optional_aligned_storage.hpp>
54
55 #ifdef BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL
56 #include <boost/optional/detail/old_optional_implementation.hpp>
57 #else
58 namespace boost {
59
60 namespace optional_ns {
61
62 // a tag for in-place initialization of contained value
63 struct in_place_init_t
64 {
65 struct init_tag{};
66 explicit in_place_init_t(init_tag){}
67 };
68 const in_place_init_t in_place_init ((in_place_init_t::init_tag()));
69
70 // a tag for conditional in-place initialization of contained value
71 struct in_place_init_if_t
72 {
73 struct init_tag{};
74 explicit in_place_init_if_t(init_tag){}
75 };
76 const in_place_init_if_t in_place_init_if ((in_place_init_if_t::init_tag()));
77
78 } // namespace optional_ns
79
80 using optional_ns::in_place_init_t;
81 using optional_ns::in_place_init;
82 using optional_ns::in_place_init_if_t;
83 using optional_ns::in_place_init_if;
84
85 namespace optional_detail {
86
87 struct optional_tag {} ;
88
89
90 template<class T>
91 class optional_base : public optional_tag
92 {
93 private :
94
95 typedef aligned_storage<T> storage_type ;
96 typedef optional_base<T> this_type ;
97
98 protected :
99
100 typedef T value_type ;
101
102 protected:
103 typedef T & reference_type ;
104 typedef T const& reference_const_type ;
105 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
106 typedef T && rval_reference_type ;
107 typedef T && reference_type_of_temporary_wrapper ;
108 #endif
109 typedef T * pointer_type ;
110 typedef T const* pointer_const_type ;
111 typedef T const& argument_type ;
112
113 // Creates an optional<T> uninitialized.
114 // No-throw
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
727 template <typename U>
728 struct is_optional_related
729 : boost::conditional< boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
730 || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, none_t>::value
731 || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, in_place_init_t>::value
732 || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, in_place_init_if_t>::value,
733 boost::true_type, boost::false_type>::type
734 {};
735
736 #if !defined(BOOST_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
740 template <typename T, typename U>
741 struct 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
752 template <typename, typename>
753 struct is_convertible_to_T_or_factory : boost::true_type
754 {};
755
756 #endif // is_convertible condition
757
758 template <typename T, typename U>
759 struct 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
766 template<class T>
767 class 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
1234 namespace boost {
1235
1236 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
1237 template<class T>
1238 class 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
1250 namespace boost {
1251
1252 // Returns optional<T>(v)
1253 template<class T>
1254 inline
1255 optional<T> make_optional ( T const& v )
1256 {
1257 return optional<T>(v);
1258 }
1259
1260 // Returns optional<T>(cond,v)
1261 template<class T>
1262 inline
1263 optional<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
1270 template<class T>
1271 inline
1272 BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
1273 get ( optional<T> const& opt )
1274 {
1275 return opt.get() ;
1276 }
1277
1278 template<class T>
1279 inline
1280 BOOST_DEDUCED_TYPENAME optional<T>::reference_type
1281 get ( 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
1288 template<class T>
1289 inline
1290 BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
1291 get ( optional<T> const* opt )
1292 {
1293 return opt->get_ptr() ;
1294 }
1295
1296 template<class T>
1297 inline
1298 BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
1299 get ( 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
1306 template<class T>
1307 inline
1308 BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
1309 get_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
1314 template<class T>
1315 inline
1316 BOOST_DEDUCED_TYPENAME optional<T>::reference_type
1317 get_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
1324 template<class T>
1325 inline
1326 BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
1327 get_pointer ( optional<T> const& opt )
1328 {
1329 return opt.get_ptr() ;
1330 }
1331
1332 template<class T>
1333 inline
1334 BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
1335 get_pointer ( optional<T>& opt )
1336 {
1337 return opt.get_ptr() ;
1338 }
1339
1340 } // namespace boost
1341
1342 namespace 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.
1345 template<class CharType, class CharTrait>
1346 std::basic_ostream<CharType, CharTrait>&
1347 operator<<(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