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