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