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 | optional_base() |
141 | : |
142 | 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 | optional_base ( init_value_tag, argument_type val ) |
153 | : |
154 | m_initialized(false) |
155 | { |
156 | 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 | optional_base ( optional_base const& rhs ) |
195 | : |
196 | m_initialized(false) |
197 | { |
198 | if ( rhs.is_initialized() ) |
199 | 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 | optional_base ( optional_base&& rhs ) |
206 | BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value) |
207 | : |
208 | m_initialized(false) |
209 | { |
210 | if ( rhs.is_initialized() ) |
211 | 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 | optional_base& operator= ( optional_base const& rhs ) |
240 | { |
241 | 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 | ~optional_base() { destroy() ; } |
256 | |
257 | // Assigns from another optional<T> (deep-copies the rhs value) |
258 | void assign ( optional_base const& rhs ) |
259 | { |
260 | if (is_initialized()) |
261 | { |
262 | if ( rhs.is_initialized() ) |
263 | assign_value(rhs.get_impl()); |
264 | else destroy(); |
265 | } |
266 | else |
267 | { |
268 | if ( rhs.is_initialized() ) |
269 | construct(rhs.get_impl()); |
270 | } |
271 | } |
272 | |
273 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
274 | // Assigns from another optional<T> (deep-moves the rhs value) |
275 | void assign ( optional_base&& rhs ) |
276 | { |
277 | if (is_initialized()) |
278 | { |
279 | if ( rhs.is_initialized() ) |
280 | assign_value( boost::move(rhs.get_impl()) ); |
281 | else destroy(); |
282 | } |
283 | else |
284 | { |
285 | if ( rhs.is_initialized() ) |
286 | construct(boost::move(rhs.get_impl())); |
287 | } |
288 | } |
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 | void assign ( rval_reference_type val ) |
348 | { |
349 | if (is_initialized()) |
350 | assign_value( boost::move(val) ); |
351 | 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 | pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; } |
395 | |
396 | bool is_initialized() const BOOST_NOEXCEPT { return m_initialized ; } |
397 | |
398 | protected : |
399 | |
400 | void construct ( argument_type val ) |
401 | { |
402 | ::new (m_storage.address()) value_type(val) ; |
403 | m_initialized = true ; |
404 | } |
405 | |
406 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
407 | void construct ( rval_reference_type val ) |
408 | { |
409 | ::new (m_storage.address()) value_type( boost::move(val) ) ; |
410 | m_initialized = true ; |
411 | } |
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 | void assign_value ( argument_type val ) { get_impl() = val; } |
750 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
751 | void assign_value ( rval_reference_type val ) { get_impl() = static_cast<rval_reference_type>(val); } |
752 | #endif |
753 | |
754 | void destroy() |
755 | { |
756 | if ( m_initialized ) |
757 | destroy_impl() ; |
758 | } |
759 | |
760 | reference_const_type get_impl() const { return m_storage.ref() ; } |
761 | reference_type get_impl() { return m_storage.ref() ; } |
762 | |
763 | pointer_const_type get_ptr_impl() const { return m_storage.ptr_ref(); } |
764 | 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 | 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 metafunction 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, bool = is_optional_related<U>::value> |
817 | struct is_optional_val_init_candidate |
818 | : boost::false_type |
819 | {}; |
820 | |
821 | template <typename T, typename U> |
822 | struct is_optional_val_init_candidate<T, U, false> |
823 | : boost::conditional< is_convertible_to_T_or_factory<T, U>::value |
824 | , boost::true_type, boost::false_type>::type |
825 | {}; |
826 | |
827 | } // namespace optional_detail |
828 | |
829 | namespace optional_config { |
830 | |
831 | template <typename T> |
832 | struct optional_uses_direct_storage_for |
833 | : boost::conditional<(boost::is_scalar<T>::value && !boost::is_const<T>::value && !boost::is_volatile<T>::value) |
834 | , boost::true_type, boost::false_type>::type |
835 | {}; |
836 | |
837 | } // namespace optional_config |
838 | |
839 | |
840 | #ifndef BOOST_OPTIONAL_DETAIL_NO_DIRECT_STORAGE_SPEC |
841 | # define BOOST_OPTIONAL_BASE_TYPE(T) boost::conditional< optional_config::optional_uses_direct_storage_for<T>::value, \ |
842 | optional_detail::tc_optional_base<T>, \ |
843 | optional_detail::optional_base<T> \ |
844 | >::type |
845 | #else |
846 | # define BOOST_OPTIONAL_BASE_TYPE(T) optional_detail::optional_base<T> |
847 | #endif |
848 | |
849 | template<class T> |
850 | class optional |
851 | : public BOOST_OPTIONAL_BASE_TYPE(T) |
852 | { |
853 | typedef typename BOOST_OPTIONAL_BASE_TYPE(T) base ; |
854 | |
855 | public : |
856 | |
857 | typedef optional<T> this_type ; |
858 | |
859 | typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ; |
860 | typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ; |
861 | typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ; |
862 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
863 | typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type rval_reference_type ; |
864 | typedef BOOST_DEDUCED_TYPENAME base::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ; |
865 | #endif |
866 | typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ; |
867 | typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ; |
868 | typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ; |
869 | |
870 | // Creates an optional<T> uninitialized. |
871 | // No-throw |
872 | optional() BOOST_NOEXCEPT : base() {} |
873 | |
874 | // Creates an optional<T> uninitialized. |
875 | // No-throw |
876 | optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {} |
877 | |
878 | // Creates an optional<T> initialized with 'val'. |
879 | // Can throw if T::T(T const&) does |
880 | optional ( argument_type val ) : base(optional_detail::init_value_tag(), val) {} |
881 | |
882 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
883 | // Creates an optional<T> initialized with 'move(val)'. |
884 | // Can throw if T::T(T &&) does |
885 | optional ( rval_reference_type val ) : base(optional_detail::init_value_tag(), boost::forward<T>(val)) |
886 | {} |
887 | #endif |
888 | |
889 | // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional. |
890 | // Can throw if T::T(T const&) does |
891 | optional ( bool cond, argument_type val ) : base(cond,val) {} |
892 | |
893 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
894 | /// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional. |
895 | // Can throw if T::T(T &&) does |
896 | optional ( bool cond, rval_reference_type val ) : base( cond, boost::forward<T>(val) ) |
897 | {} |
898 | #endif |
899 | |
900 | // NOTE: MSVC needs templated versions first |
901 | |
902 | // Creates a deep copy of another convertible optional<U> |
903 | // Requires a valid conversion from U to T. |
904 | // Can throw if T::T(U const&) does |
905 | template<class U> |
906 | explicit optional ( optional<U> const& rhs |
907 | #ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS |
908 | ,BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_constructible<T, U const&>, bool>::type = true |
909 | #endif |
910 | ) |
911 | : |
912 | base() |
913 | { |
914 | if ( rhs.is_initialized() ) |
915 | this->construct(rhs.get()); |
916 | } |
917 | |
918 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
919 | // Creates a deep move of another convertible optional<U> |
920 | // Requires a valid conversion from U to T. |
921 | // Can throw if T::T(U&&) does |
922 | template<class U> |
923 | explicit optional ( optional<U> && rhs |
924 | #ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS |
925 | ,BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_constructible<T, U>, bool>::type = true |
926 | #endif |
927 | ) |
928 | : |
929 | base() |
930 | { |
931 | if ( rhs.is_initialized() ) |
932 | this->construct( boost::move(rhs.get()) ); |
933 | } |
934 | #endif |
935 | |
936 | #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT |
937 | // Creates an optional<T> with an expression which can be either |
938 | // (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n); |
939 | // (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n); |
940 | // (c) Any expression implicitly convertible to the single type |
941 | // of a one-argument T's constructor. |
942 | // (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U> |
943 | // even though explicit overloads are present for these. |
944 | // Depending on the above some T ctor is called. |
945 | // Can throw if the resolved T ctor throws. |
946 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
947 | |
948 | |
949 | template<class Expr> |
950 | explicit optional ( Expr&& expr, |
951 | BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_val_init_candidate<T, Expr>, bool>::type = true |
952 | ) |
953 | : base(boost::forward<Expr>(expr),boost::addressof(expr)) |
954 | {} |
955 | |
956 | #else |
957 | template<class Expr> |
958 | explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {} |
959 | #endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
960 | #endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT |
961 | |
962 | // Creates a deep copy of another optional<T> |
963 | // Can throw if T::T(T const&) does |
964 | #ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS |
965 | optional ( optional const& ) = default; |
966 | #else |
967 | optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {} |
968 | #endif |
969 | |
970 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
971 | // Creates a deep move of another optional<T> |
972 | // Can throw if T::T(T&&) does |
973 | |
974 | #ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS |
975 | optional ( optional && ) = default; |
976 | #else |
977 | optional ( optional && rhs ) |
978 | BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value) |
979 | : base( boost::move(rhs) ) |
980 | {} |
981 | #endif |
982 | |
983 | #endif |
984 | |
985 | #if BOOST_WORKAROUND(_MSC_VER, <= 1600) |
986 | // On old MSVC compilers the implicitly declared dtor is not called |
987 | ~optional() {} |
988 | #endif |
989 | |
990 | |
991 | #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION) |
992 | // Assigns from an expression. See corresponding constructor. |
993 | // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED |
994 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
995 | |
996 | template<class Expr> |
997 | BOOST_DEDUCED_TYPENAME boost::enable_if<optional_detail::is_optional_val_init_candidate<T, Expr>, optional&>::type |
998 | operator= ( Expr&& expr ) |
999 | { |
1000 | this->assign_expr(boost::forward<Expr>(expr),boost::addressof(expr)); |
1001 | return *this ; |
1002 | } |
1003 | |
1004 | #else |
1005 | template<class Expr> |
1006 | optional& operator= ( Expr const& expr ) |
1007 | { |
1008 | this->assign_expr(expr,boost::addressof(expr)); |
1009 | return *this ; |
1010 | } |
1011 | #endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
1012 | #endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION) |
1013 | |
1014 | // Copy-assigns from another convertible optional<U> (converts && deep-copies the rhs value) |
1015 | // Requires a valid conversion from U to T. |
1016 | // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED |
1017 | template<class U> |
1018 | optional& operator= ( optional<U> const& rhs ) |
1019 | { |
1020 | this->assign(rhs); |
1021 | return *this ; |
1022 | } |
1023 | |
1024 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
1025 | // Move-assigns from another convertible optional<U> (converts && deep-moves the rhs value) |
1026 | // Requires a valid conversion from U to T. |
1027 | // Basic Guarantee: If T::T( U && ) throws, this is left UNINITIALIZED |
1028 | template<class U> |
1029 | optional& operator= ( optional<U> && rhs ) |
1030 | { |
1031 | this->assign(boost::move(rhs)); |
1032 | return *this ; |
1033 | } |
1034 | #endif |
1035 | |
1036 | // Assigns from another optional<T> (deep-copies the rhs value) |
1037 | // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED |
1038 | // (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw) |
1039 | #ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS |
1040 | optional& operator= ( optional const& rhs ) = default; |
1041 | #else |
1042 | optional& operator= ( optional const& rhs ) |
1043 | { |
1044 | this->assign( static_cast<base const&>(rhs) ) ; |
1045 | return *this ; |
1046 | } |
1047 | #endif |
1048 | |
1049 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
1050 | // Assigns from another optional<T> (deep-moves the rhs value) |
1051 | #ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS |
1052 | optional& operator= ( optional && ) = default; |
1053 | #else |
1054 | optional& operator= ( optional && rhs ) |
1055 | BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value) |
1056 | { |
1057 | this->assign( static_cast<base &&>(rhs) ) ; |
1058 | return *this ; |
1059 | } |
1060 | #endif |
1061 | |
1062 | #endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
1063 | |
1064 | #ifndef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX |
1065 | |
1066 | // Assigns from a T (deep-moves/copies the rhs value) |
1067 | template <typename T_> |
1068 | BOOST_DEDUCED_TYPENAME boost::enable_if<boost::is_same<T, BOOST_DEDUCED_TYPENAME boost::decay<T_>::type>, optional&>::type |
1069 | operator= ( T_&& val ) |
1070 | { |
1071 | this->assign( boost::forward<T_>(val) ) ; |
1072 | return *this ; |
1073 | } |
1074 | |
1075 | #else |
1076 | |
1077 | // Assigns from a T (deep-copies the rhs value) |
1078 | // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED |
1079 | optional& operator= ( argument_type val ) |
1080 | { |
1081 | this->assign( val ) ; |
1082 | return *this ; |
1083 | } |
1084 | |
1085 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
1086 | // Assigns from a T (deep-moves the rhs value) |
1087 | optional& operator= ( rval_reference_type val ) |
1088 | { |
1089 | this->assign( boost::move(val) ) ; |
1090 | return *this ; |
1091 | } |
1092 | #endif |
1093 | |
1094 | #endif // BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX |
1095 | |
1096 | // Assigns from a "none" |
1097 | // Which destroys the current value, if any, leaving this UNINITIALIZED |
1098 | // No-throw (assuming T::~T() doesn't) |
1099 | optional& operator= ( none_t none_ ) BOOST_NOEXCEPT |
1100 | { |
1101 | this->assign( none_ ) ; |
1102 | return *this ; |
1103 | } |
1104 | |
1105 | #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) |
1106 | // Constructs in-place |
1107 | // upon exception *this is always uninitialized |
1108 | template<class... Args> |
1109 | void emplace ( Args&&... args ) |
1110 | { |
1111 | this->emplace_assign( boost::forward<Args>(args)... ); |
1112 | } |
1113 | |
1114 | template<class... Args> |
1115 | explicit optional ( in_place_init_t, Args&&... args ) |
1116 | : base( in_place_init, boost::forward<Args>(args)... ) |
1117 | {} |
1118 | |
1119 | template<class... Args> |
1120 | explicit optional ( in_place_init_if_t, bool cond, Args&&... args ) |
1121 | : base( in_place_init_if, cond, boost::forward<Args>(args)... ) |
1122 | {} |
1123 | |
1124 | #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) |
1125 | template<class Arg> |
1126 | void emplace ( Arg&& arg ) |
1127 | { |
1128 | this->emplace_assign( boost::forward<Arg>(arg) ); |
1129 | } |
1130 | |
1131 | void emplace () |
1132 | { |
1133 | this->emplace_assign(); |
1134 | } |
1135 | |
1136 | template<class Args> |
1137 | explicit optional ( in_place_init_t, Args&& args ) |
1138 | : base( in_place_init, boost::forward<Args>(args) ) |
1139 | {} |
1140 | |
1141 | explicit optional ( in_place_init_t ) |
1142 | : base( in_place_init ) |
1143 | {} |
1144 | |
1145 | template<class Args> |
1146 | explicit optional ( in_place_init_if_t, bool cond, Args&& args ) |
1147 | : base( in_place_init_if, cond, boost::forward<Args>(args) ) |
1148 | {} |
1149 | |
1150 | explicit optional ( in_place_init_if_t, bool cond ) |
1151 | : base( in_place_init_if, cond ) |
1152 | {} |
1153 | #else |
1154 | template<class Arg> |
1155 | void emplace ( const Arg& arg ) |
1156 | { |
1157 | this->emplace_assign( arg ); |
1158 | } |
1159 | |
1160 | template<class Arg> |
1161 | void emplace ( Arg& arg ) |
1162 | { |
1163 | this->emplace_assign( arg ); |
1164 | } |
1165 | |
1166 | void emplace () |
1167 | { |
1168 | this->emplace_assign(); |
1169 | } |
1170 | |
1171 | template<class Arg> |
1172 | explicit optional ( in_place_init_t, const Arg& arg ) |
1173 | : base( in_place_init, arg ) |
1174 | {} |
1175 | |
1176 | template<class Arg> |
1177 | explicit optional ( in_place_init_t, Arg& arg ) |
1178 | : base( in_place_init, arg ) |
1179 | {} |
1180 | |
1181 | explicit optional ( in_place_init_t ) |
1182 | : base( in_place_init ) |
1183 | {} |
1184 | |
1185 | template<class Arg> |
1186 | explicit optional ( in_place_init_if_t, bool cond, const Arg& arg ) |
1187 | : base( in_place_init_if, cond, arg ) |
1188 | {} |
1189 | |
1190 | template<class Arg> |
1191 | explicit optional ( in_place_init_if_t, bool cond, Arg& arg ) |
1192 | : base( in_place_init_if, cond, arg ) |
1193 | {} |
1194 | |
1195 | explicit optional ( in_place_init_if_t, bool cond ) |
1196 | : base( in_place_init_if, cond ) |
1197 | {} |
1198 | #endif |
1199 | |
1200 | void swap( optional & arg ) |
1201 | BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value) |
1202 | { |
1203 | // allow for Koenig lookup |
1204 | boost::swap(*this, arg); |
1205 | } |
1206 | |
1207 | |
1208 | // Returns a reference to the value if this is initialized, otherwise, |
1209 | // the behaviour is UNDEFINED |
1210 | // No-throw |
1211 | reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); } |
1212 | reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); } |
1213 | |
1214 | // Returns a copy of the value if this is initialized, 'v' otherwise |
1215 | reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; } |
1216 | reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; } |
1217 | |
1218 | // Returns a pointer to the value if this is initialized, otherwise, |
1219 | // the behaviour is UNDEFINED |
1220 | // No-throw |
1221 | pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; } |
1222 | pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; } |
1223 | |
1224 | // Returns a reference to the value if this is initialized, otherwise, |
1225 | // the behaviour is UNDEFINED |
1226 | // No-throw |
1227 | #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) |
1228 | reference_const_type operator *() const& { return this->get() ; } |
1229 | reference_type operator *() & { return this->get() ; } |
1230 | reference_type_of_temporary_wrapper operator *() && { return boost::move(this->get()) ; } |
1231 | #else |
1232 | reference_const_type operator *() const { return this->get() ; } |
1233 | reference_type operator *() { return this->get() ; } |
1234 | #endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS |
1235 | |
1236 | #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) |
1237 | reference_const_type value() const& |
1238 | { |
1239 | if (this->is_initialized()) |
1240 | return this->get() ; |
1241 | else |
1242 | throw_exception(e: bad_optional_access()); |
1243 | } |
1244 | |
1245 | reference_type value() & |
1246 | { |
1247 | if (this->is_initialized()) |
1248 | return this->get() ; |
1249 | else |
1250 | throw_exception(e: bad_optional_access()); |
1251 | } |
1252 | |
1253 | reference_type_of_temporary_wrapper value() && |
1254 | { |
1255 | if (this->is_initialized()) |
1256 | return boost::move(this->get()) ; |
1257 | else |
1258 | throw_exception(e: bad_optional_access()); |
1259 | } |
1260 | |
1261 | #else |
1262 | reference_const_type value() const |
1263 | { |
1264 | if (this->is_initialized()) |
1265 | return this->get() ; |
1266 | else |
1267 | throw_exception(bad_optional_access()); |
1268 | } |
1269 | |
1270 | reference_type value() |
1271 | { |
1272 | if (this->is_initialized()) |
1273 | return this->get() ; |
1274 | else |
1275 | throw_exception(bad_optional_access()); |
1276 | } |
1277 | #endif |
1278 | |
1279 | |
1280 | #ifndef BOOST_NO_CXX11_REF_QUALIFIERS |
1281 | template <class U> |
1282 | value_type value_or ( U&& v ) const& |
1283 | { |
1284 | if (this->is_initialized()) |
1285 | return get(); |
1286 | else |
1287 | return boost::forward<U>(v); |
1288 | } |
1289 | |
1290 | template <class U> |
1291 | value_type value_or ( U&& v ) && |
1292 | { |
1293 | if (this->is_initialized()) |
1294 | return boost::move(get()); |
1295 | else |
1296 | return boost::forward<U>(v); |
1297 | } |
1298 | #elif !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
1299 | template <class U> |
1300 | value_type value_or ( U&& v ) const |
1301 | { |
1302 | if (this->is_initialized()) |
1303 | return get(); |
1304 | else |
1305 | return boost::forward<U>(v); |
1306 | } |
1307 | #else |
1308 | template <class U> |
1309 | value_type value_or ( U const& v ) const |
1310 | { |
1311 | if (this->is_initialized()) |
1312 | return get(); |
1313 | else |
1314 | return v; |
1315 | } |
1316 | |
1317 | template <class U> |
1318 | value_type value_or ( U& v ) const |
1319 | { |
1320 | if (this->is_initialized()) |
1321 | return get(); |
1322 | else |
1323 | return v; |
1324 | } |
1325 | #endif |
1326 | |
1327 | |
1328 | #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) |
1329 | template <typename F> |
1330 | value_type value_or_eval ( F f ) const& |
1331 | { |
1332 | if (this->is_initialized()) |
1333 | return get(); |
1334 | else |
1335 | return f(); |
1336 | } |
1337 | |
1338 | template <typename F> |
1339 | value_type value_or_eval ( F f ) && |
1340 | { |
1341 | if (this->is_initialized()) |
1342 | return boost::move(get()); |
1343 | else |
1344 | return f(); |
1345 | } |
1346 | |
1347 | template <typename F> |
1348 | optional<typename boost::result_of<F(reference_type)>::type> map(F f) & |
1349 | { |
1350 | if (this->has_value()) |
1351 | return f(get()); |
1352 | else |
1353 | return none; |
1354 | } |
1355 | |
1356 | template <typename F> |
1357 | optional<typename boost::result_of<F(reference_const_type)>::type> map(F f) const& |
1358 | { |
1359 | if (this->has_value()) |
1360 | return f(get()); |
1361 | else |
1362 | return none; |
1363 | } |
1364 | |
1365 | template <typename F> |
1366 | optional<typename boost::result_of<F(reference_type_of_temporary_wrapper)>::type> map(F f) && |
1367 | { |
1368 | if (this->has_value()) |
1369 | return f(boost::move(this->get())); |
1370 | else |
1371 | return none; |
1372 | } |
1373 | |
1374 | template <typename F> |
1375 | optional<typename optional_detail::optional_value_type<typename boost::result_of<F(reference_type)>::type>::type> flat_map(F f) & |
1376 | { |
1377 | if (this->has_value()) |
1378 | return f(get()); |
1379 | else |
1380 | return none; |
1381 | } |
1382 | |
1383 | template <typename F> |
1384 | optional<typename optional_detail::optional_value_type<typename boost::result_of<F(reference_const_type)>::type>::type> flat_map(F f) const& |
1385 | { |
1386 | if (this->has_value()) |
1387 | return f(get()); |
1388 | else |
1389 | return none; |
1390 | } |
1391 | |
1392 | template <typename F> |
1393 | optional<typename optional_detail::optional_value_type<typename boost::result_of<F(reference_type_of_temporary_wrapper)>::type>::type> flat_map(F f) && |
1394 | { |
1395 | if (this->has_value()) |
1396 | return f(boost::move(get())); |
1397 | else |
1398 | return none; |
1399 | } |
1400 | |
1401 | #else |
1402 | template <typename F> |
1403 | value_type value_or_eval ( F f ) const |
1404 | { |
1405 | if (this->is_initialized()) |
1406 | return get(); |
1407 | else |
1408 | return f(); |
1409 | } |
1410 | |
1411 | template <typename F> |
1412 | optional<typename boost::result_of<F(reference_type)>::type> map(F f) |
1413 | { |
1414 | if (this->has_value()) |
1415 | return f(get()); |
1416 | else |
1417 | return none; |
1418 | } |
1419 | |
1420 | template <typename F> |
1421 | optional<typename boost::result_of<F(reference_const_type)>::type> map(F f) const |
1422 | { |
1423 | if (this->has_value()) |
1424 | return f(get()); |
1425 | else |
1426 | return none; |
1427 | } |
1428 | |
1429 | template <typename F> |
1430 | optional<typename optional_detail::optional_value_type<typename boost::result_of<F(reference_type)>::type>::type> flat_map(F f) |
1431 | { |
1432 | if (this->has_value()) |
1433 | return f(get()); |
1434 | else |
1435 | return none; |
1436 | } |
1437 | |
1438 | template <typename F> |
1439 | optional<typename optional_detail::optional_value_type<typename boost::result_of<F(reference_const_type)>::type>::type> flat_map(F f) const |
1440 | { |
1441 | if (this->has_value()) |
1442 | return f(get()); |
1443 | else |
1444 | return none; |
1445 | } |
1446 | |
1447 | #endif |
1448 | |
1449 | bool has_value() const BOOST_NOEXCEPT { return this->is_initialized() ; } |
1450 | |
1451 | bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; } |
1452 | |
1453 | BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() |
1454 | } ; |
1455 | |
1456 | } // namespace boost |
1457 | |
1458 | #endif // BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL |
1459 | |
1460 | namespace boost { |
1461 | |
1462 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
1463 | template<class T> |
1464 | class optional<T&&> |
1465 | { |
1466 | BOOST_STATIC_ASSERT_MSG(sizeof(T) == 0, "Optional rvalue references are illegal." ); |
1467 | } ; |
1468 | #endif |
1469 | |
1470 | } // namespace boost |
1471 | |
1472 | #ifndef BOOST_OPTIONAL_CONFIG_DONT_SPECIALIZE_OPTIONAL_REFS |
1473 | # include <boost/optional/detail/optional_reference_spec.hpp> |
1474 | #endif |
1475 | |
1476 | namespace boost { |
1477 | |
1478 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
1479 | |
1480 | template<class T> |
1481 | inline |
1482 | optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type> make_optional ( T && v ) |
1483 | { |
1484 | return optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type>(boost::forward<T>(v)); |
1485 | } |
1486 | |
1487 | // Returns optional<T>(cond,v) |
1488 | template<class T> |
1489 | inline |
1490 | optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type> make_optional ( bool cond, T && v ) |
1491 | { |
1492 | return optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type>(cond,boost::forward<T>(v)); |
1493 | } |
1494 | |
1495 | #else |
1496 | |
1497 | // Returns optional<T>(v) |
1498 | template<class T> |
1499 | inline |
1500 | optional<T> make_optional ( T const& v ) |
1501 | { |
1502 | return optional<T>(v); |
1503 | } |
1504 | |
1505 | // Returns optional<T>(cond,v) |
1506 | template<class T> |
1507 | inline |
1508 | optional<T> make_optional ( bool cond, T const& v ) |
1509 | { |
1510 | return optional<T>(cond,v); |
1511 | } |
1512 | |
1513 | #endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES |
1514 | |
1515 | // Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED. |
1516 | // No-throw |
1517 | template<class T> |
1518 | inline |
1519 | BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type |
1520 | get ( optional<T> const& opt ) |
1521 | { |
1522 | return opt.get() ; |
1523 | } |
1524 | |
1525 | template<class T> |
1526 | inline |
1527 | BOOST_DEDUCED_TYPENAME optional<T>::reference_type |
1528 | get ( optional<T>& opt ) |
1529 | { |
1530 | return opt.get() ; |
1531 | } |
1532 | |
1533 | // Returns a pointer to the value if this is initialized, otherwise, returns NULL. |
1534 | // No-throw |
1535 | template<class T> |
1536 | inline |
1537 | BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type |
1538 | get ( optional<T> const* opt ) |
1539 | { |
1540 | return opt->get_ptr() ; |
1541 | } |
1542 | |
1543 | template<class T> |
1544 | inline |
1545 | BOOST_DEDUCED_TYPENAME optional<T>::pointer_type |
1546 | get ( optional<T>* opt ) |
1547 | { |
1548 | return opt->get_ptr() ; |
1549 | } |
1550 | |
1551 | // Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED. |
1552 | // No-throw |
1553 | template<class T> |
1554 | inline |
1555 | BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type |
1556 | get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v ) |
1557 | { |
1558 | return opt.get_value_or(v) ; |
1559 | } |
1560 | |
1561 | template<class T> |
1562 | inline |
1563 | BOOST_DEDUCED_TYPENAME optional<T>::reference_type |
1564 | get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v ) |
1565 | { |
1566 | return opt.get_value_or(v) ; |
1567 | } |
1568 | |
1569 | // Returns a pointer to the value if this is initialized, otherwise, returns NULL. |
1570 | // No-throw |
1571 | template<class T> |
1572 | inline |
1573 | BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type |
1574 | get_pointer ( optional<T> const& opt ) |
1575 | { |
1576 | return opt.get_ptr() ; |
1577 | } |
1578 | |
1579 | template<class T> |
1580 | inline |
1581 | BOOST_DEDUCED_TYPENAME optional<T>::pointer_type |
1582 | get_pointer ( optional<T>& opt ) |
1583 | { |
1584 | return opt.get_ptr() ; |
1585 | } |
1586 | |
1587 | } // namespace boost |
1588 | |
1589 | namespace boost { |
1590 | |
1591 | // The following declaration prevents a bug where operator safe-bool is used upon streaming optional object if you forget the IO header. |
1592 | template<class CharType, class CharTrait> |
1593 | std::basic_ostream<CharType, CharTrait>& |
1594 | operator<<(std::basic_ostream<CharType, CharTrait>& os, optional_detail::optional_tag const&) |
1595 | { |
1596 | BOOST_STATIC_ASSERT_MSG(sizeof(CharType) == 0, "If you want to output boost::optional, include header <boost/optional/optional_io.hpp>" ); |
1597 | return os; |
1598 | } |
1599 | |
1600 | } // namespace boost |
1601 | |
1602 | #include <boost/optional/detail/optional_relops.hpp> |
1603 | #include <boost/optional/detail/optional_swap.hpp> |
1604 | |
1605 | #endif // header guard |
1606 | |