]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40500) && !defined(__SUNPRO_CC) | |
737 | // this condition is a copy paste from is_constructible.hpp | |
738 | // I also disable SUNPRO, as it seems not to support type_traits correctly | |
739 | ||
740 | template <typename T, typename U> | |
741 | struct is_convertible_to_T_or_factory | |
742 | : boost::conditional< boost::is_base_of<boost::in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value | |
743 | || boost::is_base_of<boost::typed_in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value | |
744 | || boost::is_constructible<T, U&&>::value | |
745 | , boost::true_type, boost::false_type>::type | |
746 | {}; | |
747 | ||
748 | #else | |
749 | ||
750 | #define BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT | |
751 | ||
752 | template <typename, typename> | |
753 | struct is_convertible_to_T_or_factory : boost::true_type | |
754 | {}; | |
755 | ||
756 | #endif // is_convertible condition | |
757 | ||
758 | template <typename T, typename U> | |
759 | struct is_optional_val_init_candidate | |
760 | : boost::conditional< !is_optional_related<U>::value && is_convertible_to_T_or_factory<T, U>::value | |
761 | , boost::true_type, boost::false_type>::type | |
762 | {}; | |
763 | ||
764 | } // namespace optional_detail | |
765 | ||
766 | template<class T> | |
767 | class optional : public optional_detail::optional_base<T> | |
768 | { | |
769 | typedef optional_detail::optional_base<T> base ; | |
770 | ||
771 | public : | |
772 | ||
773 | typedef optional<T> this_type ; | |
774 | ||
775 | typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ; | |
776 | typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ; | |
777 | typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ; | |
778 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES | |
779 | typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type rval_reference_type ; | |
780 | typedef BOOST_DEDUCED_TYPENAME base::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ; | |
781 | #endif | |
782 | typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ; | |
783 | typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ; | |
784 | typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ; | |
785 | ||
786 | // Creates an optional<T> uninitialized. | |
787 | // No-throw | |
788 | optional() BOOST_NOEXCEPT : base() {} | |
789 | ||
790 | // Creates an optional<T> uninitialized. | |
791 | // No-throw | |
792 | optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {} | |
793 | ||
794 | // Creates an optional<T> initialized with 'val'. | |
795 | // Can throw if T::T(T const&) does | |
796 | optional ( argument_type val ) : base(val) {} | |
797 | ||
798 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES | |
799 | // Creates an optional<T> initialized with 'move(val)'. | |
800 | // Can throw if T::T(T &&) does | |
801 | optional ( rval_reference_type val ) : base( boost::forward<T>(val) ) | |
802 | {} | |
803 | #endif | |
804 | ||
805 | // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional. | |
806 | // Can throw if T::T(T const&) does | |
807 | optional ( bool cond, argument_type val ) : base(cond,val) {} | |
808 | ||
809 | // NOTE: MSVC needs templated versions first | |
810 | ||
811 | // Creates a deep copy of another convertible optional<U> | |
812 | // Requires a valid conversion from U to T. | |
813 | // Can throw if T::T(U const&) does | |
814 | template<class U> | |
815 | explicit optional ( optional<U> const& rhs ) | |
816 | : | |
817 | base() | |
818 | { | |
819 | if ( rhs.is_initialized() ) | |
820 | this->construct(rhs.get()); | |
821 | } | |
822 | ||
823 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES | |
824 | // Creates a deep move of another convertible optional<U> | |
825 | // Requires a valid conversion from U to T. | |
826 | // Can throw if T::T(U&&) does | |
827 | template<class U> | |
828 | explicit optional ( optional<U> && rhs ) | |
829 | : | |
830 | base() | |
831 | { | |
832 | if ( rhs.is_initialized() ) | |
833 | this->construct( boost::move(rhs.get()) ); | |
834 | } | |
835 | #endif | |
836 | ||
837 | #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT | |
838 | // Creates an optional<T> with an expression which can be either | |
839 | // (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n); | |
840 | // (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n); | |
841 | // (c) Any expression implicitly convertible to the single type | |
842 | // of a one-argument T's constructor. | |
843 | // (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U> | |
844 | // even though explicit overloads are present for these. | |
845 | // Depending on the above some T ctor is called. | |
846 | // Can throw if the resolved T ctor throws. | |
847 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES | |
848 | ||
849 | ||
850 | template<class Expr> | |
851 | explicit optional ( Expr&& expr, | |
852 | BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_val_init_candidate<T, Expr> >::type* = 0 | |
853 | ) | |
854 | : base(boost::forward<Expr>(expr),boost::addressof(expr)) | |
855 | {} | |
856 | ||
857 | #else | |
858 | template<class Expr> | |
859 | explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {} | |
860 | #endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES | |
861 | #endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT | |
862 | ||
863 | // Creates a deep copy of another optional<T> | |
864 | // Can throw if T::T(T const&) does | |
865 | optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {} | |
866 | ||
867 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES | |
868 | // Creates a deep move of another optional<T> | |
869 | // Can throw if T::T(T&&) does | |
870 | optional ( optional && rhs ) | |
871 | BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value) | |
872 | : base( boost::move(rhs) ) | |
873 | {} | |
874 | ||
875 | #endif | |
876 | ||
877 | #if BOOST_WORKAROUND(_MSC_VER, <= 1600) | |
878 | // On old MSVC compilers the implicitly declared dtor is not called | |
879 | ~optional() {} | |
880 | #endif | |
881 | ||
882 | ||
883 | #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION) | |
884 | // Assigns from an expression. See corresponding constructor. | |
885 | // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED | |
886 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES | |
887 | ||
888 | template<class Expr> | |
889 | BOOST_DEDUCED_TYPENAME boost::enable_if<optional_detail::is_optional_val_init_candidate<T, Expr>, optional&>::type | |
890 | operator= ( Expr&& expr ) | |
891 | { | |
892 | this->assign_expr(boost::forward<Expr>(expr),boost::addressof(expr)); | |
893 | return *this ; | |
894 | } | |
895 | ||
896 | #else | |
897 | template<class Expr> | |
898 | optional& operator= ( Expr const& expr ) | |
899 | { | |
900 | this->assign_expr(expr,boost::addressof(expr)); | |
901 | return *this ; | |
902 | } | |
903 | #endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES | |
904 | #endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION) | |
905 | ||
906 | // Copy-assigns from another convertible optional<U> (converts && deep-copies the rhs value) | |
907 | // Requires a valid conversion from U to T. | |
908 | // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED | |
909 | template<class U> | |
910 | optional& operator= ( optional<U> const& rhs ) | |
911 | { | |
912 | this->assign(rhs); | |
913 | return *this ; | |
914 | } | |
915 | ||
916 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES | |
917 | // Move-assigns from another convertible optional<U> (converts && deep-moves the rhs value) | |
918 | // Requires a valid conversion from U to T. | |
919 | // Basic Guarantee: If T::T( U && ) throws, this is left UNINITIALIZED | |
920 | template<class U> | |
921 | optional& operator= ( optional<U> && rhs ) | |
922 | { | |
923 | this->assign(boost::move(rhs)); | |
924 | return *this ; | |
925 | } | |
926 | #endif | |
927 | ||
928 | // Assigns from another optional<T> (deep-copies the rhs value) | |
929 | // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED | |
930 | // (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw) | |
931 | optional& operator= ( optional const& rhs ) | |
932 | { | |
933 | this->assign( static_cast<base const&>(rhs) ) ; | |
934 | return *this ; | |
935 | } | |
936 | ||
937 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES | |
938 | // Assigns from another optional<T> (deep-moves the rhs value) | |
939 | optional& operator= ( optional && rhs ) | |
940 | BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value) | |
941 | { | |
942 | this->assign( static_cast<base &&>(rhs) ) ; | |
943 | return *this ; | |
944 | } | |
945 | #endif | |
946 | ||
947 | // Assigns from a T (deep-copies the rhs value) | |
948 | // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED | |
949 | optional& operator= ( argument_type val ) | |
950 | { | |
951 | this->assign( val ) ; | |
952 | return *this ; | |
953 | } | |
954 | ||
955 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES | |
956 | // Assigns from a T (deep-moves the rhs value) | |
957 | optional& operator= ( rval_reference_type val ) | |
958 | { | |
959 | this->assign( boost::move(val) ) ; | |
960 | return *this ; | |
961 | } | |
962 | #endif | |
963 | ||
964 | // Assigns from a "none" | |
965 | // Which destroys the current value, if any, leaving this UNINITIALIZED | |
966 | // No-throw (assuming T::~T() doesn't) | |
967 | optional& operator= ( none_t none_ ) BOOST_NOEXCEPT | |
968 | { | |
969 | this->assign( none_ ) ; | |
970 | return *this ; | |
971 | } | |
972 | ||
973 | #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
974 | // Constructs in-place | |
975 | // upon exception *this is always uninitialized | |
976 | template<class... Args> | |
977 | void emplace ( Args&&... args ) | |
978 | { | |
979 | this->emplace_assign( boost::forward<Args>(args)... ); | |
980 | } | |
981 | ||
982 | template<class... Args> | |
983 | explicit optional ( in_place_init_t, Args&&... args ) | |
984 | : base( in_place_init, boost::forward<Args>(args)... ) | |
985 | {} | |
986 | ||
987 | template<class... Args> | |
988 | explicit optional ( in_place_init_if_t, bool cond, Args&&... args ) | |
989 | : base( in_place_init_if, cond, boost::forward<Args>(args)... ) | |
990 | {} | |
991 | ||
992 | #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) | |
993 | template<class Arg> | |
994 | void emplace ( Arg&& arg ) | |
995 | { | |
996 | this->emplace_assign( boost::forward<Arg>(arg) ); | |
997 | } | |
998 | ||
999 | void emplace () | |
1000 | { | |
1001 | this->emplace_assign(); | |
1002 | } | |
1003 | ||
1004 | template<class Args> | |
1005 | explicit optional ( in_place_init_t, Args&& args ) | |
1006 | : base( in_place_init, boost::forward<Args>(args) ) | |
1007 | {} | |
1008 | ||
1009 | explicit optional ( in_place_init_t ) | |
1010 | : base( in_place_init ) | |
1011 | {} | |
1012 | ||
1013 | template<class Args> | |
1014 | explicit optional ( in_place_init_if_t, bool cond, Args&& args ) | |
1015 | : base( in_place_init_if, cond, boost::forward<Args>(args) ) | |
1016 | {} | |
1017 | ||
1018 | explicit optional ( in_place_init_if_t, bool cond ) | |
1019 | : base( in_place_init_if, cond ) | |
1020 | {} | |
1021 | #else | |
1022 | template<class Arg> | |
1023 | void emplace ( const Arg& arg ) | |
1024 | { | |
1025 | this->emplace_assign( arg ); | |
1026 | } | |
1027 | ||
1028 | template<class Arg> | |
1029 | void emplace ( Arg& arg ) | |
1030 | { | |
1031 | this->emplace_assign( arg ); | |
1032 | } | |
1033 | ||
1034 | void emplace () | |
1035 | { | |
1036 | this->emplace_assign(); | |
1037 | } | |
1038 | ||
1039 | template<class Arg> | |
1040 | explicit optional ( in_place_init_t, const Arg& arg ) | |
1041 | : base( in_place_init, arg ) | |
1042 | {} | |
1043 | ||
1044 | template<class Arg> | |
1045 | explicit optional ( in_place_init_t, Arg& arg ) | |
1046 | : base( in_place_init, arg ) | |
1047 | {} | |
1048 | ||
1049 | explicit optional ( in_place_init_t ) | |
1050 | : base( in_place_init ) | |
1051 | {} | |
1052 | ||
1053 | template<class Arg> | |
1054 | explicit optional ( in_place_init_if_t, bool cond, const Arg& arg ) | |
1055 | : base( in_place_init_if, cond, arg ) | |
1056 | {} | |
1057 | ||
1058 | template<class Arg> | |
1059 | explicit optional ( in_place_init_if_t, bool cond, Arg& arg ) | |
1060 | : base( in_place_init_if, cond, arg ) | |
1061 | {} | |
1062 | ||
1063 | explicit optional ( in_place_init_if_t, bool cond ) | |
1064 | : base( in_place_init_if, cond ) | |
1065 | {} | |
1066 | #endif | |
1067 | ||
1068 | void swap( optional & arg ) | |
1069 | BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value) | |
1070 | { | |
1071 | // allow for Koenig lookup | |
1072 | boost::swap(*this, arg); | |
1073 | } | |
1074 | ||
1075 | ||
1076 | // Returns a reference to the value if this is initialized, otherwise, | |
1077 | // the behaviour is UNDEFINED | |
1078 | // No-throw | |
1079 | reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); } | |
1080 | reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); } | |
1081 | ||
1082 | // Returns a copy of the value if this is initialized, 'v' otherwise | |
1083 | reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; } | |
1084 | reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; } | |
1085 | ||
1086 | // Returns a pointer to the value if this is initialized, otherwise, | |
1087 | // the behaviour is UNDEFINED | |
1088 | // No-throw | |
1089 | pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; } | |
1090 | pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; } | |
1091 | ||
1092 | // Returns a reference to the value if this is initialized, otherwise, | |
1093 | // the behaviour is UNDEFINED | |
1094 | // No-throw | |
1095 | #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) | |
1096 | reference_const_type operator *() const& { return this->get() ; } | |
1097 | reference_type operator *() & { return this->get() ; } | |
1098 | reference_type_of_temporary_wrapper operator *() && { return boost::move(this->get()) ; } | |
1099 | #else | |
1100 | reference_const_type operator *() const { return this->get() ; } | |
1101 | reference_type operator *() { return this->get() ; } | |
1102 | #endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS | |
1103 | ||
1104 | #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) | |
1105 | reference_const_type value() const& | |
1106 | { | |
1107 | if (this->is_initialized()) | |
1108 | return this->get() ; | |
1109 | else | |
1110 | throw_exception(bad_optional_access()); | |
1111 | } | |
1112 | ||
1113 | reference_type value() & | |
1114 | { | |
1115 | if (this->is_initialized()) | |
1116 | return this->get() ; | |
1117 | else | |
1118 | throw_exception(bad_optional_access()); | |
1119 | } | |
1120 | ||
1121 | reference_type_of_temporary_wrapper value() && | |
1122 | { | |
1123 | if (this->is_initialized()) | |
1124 | return boost::move(this->get()) ; | |
1125 | else | |
1126 | throw_exception(bad_optional_access()); | |
1127 | } | |
1128 | ||
1129 | #else | |
1130 | reference_const_type value() const | |
1131 | { | |
1132 | if (this->is_initialized()) | |
1133 | return this->get() ; | |
1134 | else | |
1135 | throw_exception(bad_optional_access()); | |
1136 | } | |
1137 | ||
1138 | reference_type value() | |
1139 | { | |
1140 | if (this->is_initialized()) | |
1141 | return this->get() ; | |
1142 | else | |
1143 | throw_exception(bad_optional_access()); | |
1144 | } | |
1145 | #endif | |
1146 | ||
1147 | ||
1148 | #ifndef BOOST_NO_CXX11_REF_QUALIFIERS | |
1149 | template <class U> | |
1150 | value_type value_or ( U&& v ) const& | |
1151 | { | |
1152 | if (this->is_initialized()) | |
1153 | return get(); | |
1154 | else | |
1155 | return boost::forward<U>(v); | |
1156 | } | |
1157 | ||
1158 | template <class U> | |
1159 | value_type value_or ( U&& v ) && | |
1160 | { | |
1161 | if (this->is_initialized()) | |
1162 | return boost::move(get()); | |
1163 | else | |
1164 | return boost::forward<U>(v); | |
1165 | } | |
1166 | #elif !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES | |
1167 | template <class U> | |
1168 | value_type value_or ( U&& v ) const | |
1169 | { | |
1170 | if (this->is_initialized()) | |
1171 | return get(); | |
1172 | else | |
1173 | return boost::forward<U>(v); | |
1174 | } | |
1175 | #else | |
1176 | template <class U> | |
1177 | value_type value_or ( U const& v ) const | |
1178 | { | |
1179 | if (this->is_initialized()) | |
1180 | return get(); | |
1181 | else | |
1182 | return v; | |
1183 | } | |
1184 | ||
1185 | template <class U> | |
1186 | value_type value_or ( U& v ) const | |
1187 | { | |
1188 | if (this->is_initialized()) | |
1189 | return get(); | |
1190 | else | |
1191 | return v; | |
1192 | } | |
1193 | #endif | |
1194 | ||
1195 | ||
1196 | #ifndef BOOST_NO_CXX11_REF_QUALIFIERS | |
1197 | template <typename F> | |
1198 | value_type value_or_eval ( F f ) const& | |
1199 | { | |
1200 | if (this->is_initialized()) | |
1201 | return get(); | |
1202 | else | |
1203 | return f(); | |
1204 | } | |
1205 | ||
1206 | template <typename F> | |
1207 | value_type value_or_eval ( F f ) && | |
1208 | { | |
1209 | if (this->is_initialized()) | |
1210 | return boost::move(get()); | |
1211 | else | |
1212 | return f(); | |
1213 | } | |
1214 | #else | |
1215 | template <typename F> | |
1216 | value_type value_or_eval ( F f ) const | |
1217 | { | |
1218 | if (this->is_initialized()) | |
1219 | return get(); | |
1220 | else | |
1221 | return f(); | |
1222 | } | |
1223 | #endif | |
1224 | ||
1225 | bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; } | |
1226 | ||
1227 | BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() | |
1228 | } ; | |
1229 | ||
1230 | } // namespace boost | |
1231 | ||
1232 | #endif // BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL | |
1233 | ||
1234 | namespace boost { | |
1235 | ||
1236 | #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES | |
1237 | template<class T> | |
1238 | class optional<T&&> | |
1239 | { | |
1240 | BOOST_STATIC_ASSERT_MSG(sizeof(T) == 0, "Optional rvalue references are illegal."); | |
1241 | } ; | |
1242 | #endif | |
1243 | ||
1244 | } // namespace boost | |
1245 | ||
1246 | #ifndef BOOST_OPTIONAL_CONFIG_DONT_SPECIALIZE_OPTIONAL_REFS | |
1247 | # include <boost/optional/detail/optional_reference_spec.hpp> | |
1248 | #endif | |
1249 | ||
1250 | namespace boost { | |
1251 | ||
1252 | // Returns optional<T>(v) | |
1253 | template<class T> | |
1254 | inline | |
1255 | optional<T> make_optional ( T const& v ) | |
1256 | { | |
1257 | return optional<T>(v); | |
1258 | } | |
1259 | ||
1260 | // Returns optional<T>(cond,v) | |
1261 | template<class T> | |
1262 | inline | |
1263 | optional<T> make_optional ( bool cond, T const& v ) | |
1264 | { | |
1265 | return optional<T>(cond,v); | |
1266 | } | |
1267 | ||
1268 | // Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED. | |
1269 | // No-throw | |
1270 | template<class T> | |
1271 | inline | |
1272 | BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type | |
1273 | get ( optional<T> const& opt ) | |
1274 | { | |
1275 | return opt.get() ; | |
1276 | } | |
1277 | ||
1278 | template<class T> | |
1279 | inline | |
1280 | BOOST_DEDUCED_TYPENAME optional<T>::reference_type | |
1281 | get ( optional<T>& opt ) | |
1282 | { | |
1283 | return opt.get() ; | |
1284 | } | |
1285 | ||
1286 | // Returns a pointer to the value if this is initialized, otherwise, returns NULL. | |
1287 | // No-throw | |
1288 | template<class T> | |
1289 | inline | |
1290 | BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type | |
1291 | get ( optional<T> const* opt ) | |
1292 | { | |
1293 | return opt->get_ptr() ; | |
1294 | } | |
1295 | ||
1296 | template<class T> | |
1297 | inline | |
1298 | BOOST_DEDUCED_TYPENAME optional<T>::pointer_type | |
1299 | get ( optional<T>* opt ) | |
1300 | { | |
1301 | return opt->get_ptr() ; | |
1302 | } | |
1303 | ||
1304 | // Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED. | |
1305 | // No-throw | |
1306 | template<class T> | |
1307 | inline | |
1308 | BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type | |
1309 | get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v ) | |
1310 | { | |
1311 | return opt.get_value_or(v) ; | |
1312 | } | |
1313 | ||
1314 | template<class T> | |
1315 | inline | |
1316 | BOOST_DEDUCED_TYPENAME optional<T>::reference_type | |
1317 | get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v ) | |
1318 | { | |
1319 | return opt.get_value_or(v) ; | |
1320 | } | |
1321 | ||
1322 | // Returns a pointer to the value if this is initialized, otherwise, returns NULL. | |
1323 | // No-throw | |
1324 | template<class T> | |
1325 | inline | |
1326 | BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type | |
1327 | get_pointer ( optional<T> const& opt ) | |
1328 | { | |
1329 | return opt.get_ptr() ; | |
1330 | } | |
1331 | ||
1332 | template<class T> | |
1333 | inline | |
1334 | BOOST_DEDUCED_TYPENAME optional<T>::pointer_type | |
1335 | get_pointer ( optional<T>& opt ) | |
1336 | { | |
1337 | return opt.get_ptr() ; | |
1338 | } | |
1339 | ||
1340 | } // namespace boost | |
1341 | ||
1342 | namespace boost { | |
1343 | ||
1344 | // The following declaration prevents a bug where operator safe-bool is used upon streaming optional object if you forget the IO header. | |
1345 | template<class CharType, class CharTrait> | |
1346 | std::basic_ostream<CharType, CharTrait>& | |
1347 | operator<<(std::basic_ostream<CharType, CharTrait>& os, optional_detail::optional_tag const&) | |
1348 | { | |
1349 | BOOST_STATIC_ASSERT_MSG(sizeof(CharType) == 0, "If you want to output boost::optional, include header <boost/optional/optional_io.hpp>"); | |
1350 | return os; | |
1351 | } | |
1352 | ||
1353 | } // namespace boost | |
1354 | ||
1355 | #include <boost/optional/detail/optional_relops.hpp> | |
1356 | #include <boost/optional/detail/optional_swap.hpp> | |
1357 | ||
1358 | #endif // header guard |