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 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 | 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 | 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 | 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 | 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 | 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 | operator= ( T_&& val ) |
1065 | { |
1066 | 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 | reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); } |
1207 | 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 | pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; } |
1217 | 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 | 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 | bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; } |
1447 | |
1448 | 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 | get_pointer ( optional<T>& opt ) |
1578 | { |
1579 | 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 |
1601 | |