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