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{};
in_place_init_tboost::optional_ns::in_place_init_t66 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{};
in_place_init_if_tboost::optional_ns::in_place_init_if_t74 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
optional_base()115 optional_base()
116 :
117 m_initialized(false) {}
118
119 // Creates an optional<T> uninitialized.
120 // No-throw
optional_base(none_t)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
optional_base(argument_type val)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
optional_base(rval_reference_type val)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
optional_base(bool cond,argument_type val)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
optional_base(optional_base const & rhs)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
optional_base(optional_base && rhs)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>
optional_base(Expr && expr,PtrExpr const * tag)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>
optional_base(Expr const & expr,Expr const * tag)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)
~optional_base()203 ~optional_base() { destroy() ; }
204
205 // Assigns from another optional<T> (deep-copies the rhs value)
assign(optional_base const & rhs)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)
assign(optional_base && rhs)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>
assign(optional<U> const & rhs)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>
assign(optional<U> && rhs)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)
assign(argument_type val)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)
assign(rval_reference_type val)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)
assign(none_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>
assign_expr(Expr && expr,ExprPtr const * tag)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>
assign_expr(Expr const & expr,Expr const * tag)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)
reset()333 void reset() BOOST_NOEXCEPT { destroy(); }
334
335 // **DEPPRECATED** Replaces the current value -if any- with 'val'
reset(argument_type 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
get_ptr() const341 pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
get_ptr()342 pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; }
343
is_initialized() const344 bool is_initialized() const { return m_initialized ; }
345
346 protected :
347
construct(argument_type val)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
construct(rval_reference_type val)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>
construct(in_place_init_t,Args &&...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>
emplace_assign(Args &&...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>
optional_base(in_place_init_t,Args &&...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>
optional_base(in_place_init_if_t,bool cond,Args &&...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>
construct(in_place_init_t,Arg && 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
construct(in_place_init_t)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>
emplace_assign(Arg && arg)411 void emplace_assign ( Arg&& arg )
412 {
413 destroy();
414 construct(in_place_init, boost::forward<Arg>(arg)) ;
415 }
416
emplace_assign()417 void emplace_assign ()
418 {
419 destroy();
420 construct(in_place_init) ;
421 }
422
423 template<class Arg>
optional_base(in_place_init_t,Arg && 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
optional_base(in_place_init_t)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>
optional_base(in_place_init_if_t,bool cond,Arg && 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
optional_base(in_place_init_if_t,bool cond)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>
construct(in_place_init_t,const Arg & 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>
construct(in_place_init_t,Arg & 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
construct(in_place_init_t)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>
emplace_assign(const Arg & arg)478 void emplace_assign ( const Arg& arg )
479 {
480 destroy();
481 construct(in_place_init, arg);
482 }
483
484 template<class Arg>
emplace_assign(Arg & arg)485 void emplace_assign ( Arg& arg )
486 {
487 destroy();
488 construct(in_place_init, arg);
489 }
490
emplace_assign()491 void emplace_assign ()
492 {
493 destroy();
494 construct(in_place_init);
495 }
496
497 template<class Arg>
optional_base(in_place_init_t,const Arg & 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>
optional_base(in_place_init_t,Arg & arg)505 explicit optional_base ( in_place_init_t, Arg& arg )
506 : m_initialized(false)
507 {
508 construct(in_place_init, arg);
509 }
510
optional_base(in_place_init_t)511 explicit optional_base ( in_place_init_t )
512 : m_initialized(false)
513 {
514 construct(in_place_init);
515 }
516
517 template<class Arg>
optional_base(in_place_init_if_t,bool cond,const Arg & 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>
optional_base(in_place_init_if_t,bool cond,Arg & 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
optional_base(in_place_init_if_t,bool cond)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>
construct(Expr && factory,in_place_factory_base const *)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>
construct(Expr && factory,typed_in_place_factory_base const *)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>
assign_expr_to_initialized(Expr && factory,in_place_factory_base const * tag)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>
assign_expr_to_initialized(Expr && factory,typed_in_place_factory_base const * tag)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>
construct(Expr const & factory,in_place_factory_base const *)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>
construct(Expr const & factory,typed_in_place_factory_base const *)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>
assign_expr_to_initialized(Expr const & factory,in_place_factory_base const * tag)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>
assign_expr_to_initialized(Expr const & factory,typed_in_place_factory_base const * tag)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>
construct(Expr && expr,void const *)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>
assign_expr_to_initialized(Expr && expr,void const *)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>
construct(Expr const & expr,void const *)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>
assign_expr_to_initialized(Expr const & expr,void const *)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>
construct(Expr && expr,optional_tag const *)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>
construct(Expr const & expr,optional_tag const *)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
assign_value(argument_type val)697 void assign_value ( argument_type val ) { get_impl() = val; }
698 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
assign_value(rval_reference_type val)699 void assign_value ( rval_reference_type val ) { get_impl() = static_cast<rval_reference_type>(val); }
700 #endif
701
destroy()702 void destroy()
703 {
704 if ( m_initialized )
705 destroy_impl() ;
706 }
707
get_impl() const708 reference_const_type get_impl() const { return m_storage.ref() ; }
get_impl()709 reference_type get_impl() { return m_storage.ref() ; }
710
get_ptr_impl() const711 pointer_const_type get_ptr_impl() const { return m_storage.ptr_ref(); }
get_ptr_impl()712 pointer_type get_ptr_impl() { return m_storage.ptr_ref(); }
713
714 private :
715
716 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1600)
destroy_impl()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
optional()792 optional() BOOST_NOEXCEPT : base() {}
793
794 // Creates an optional<T> uninitialized.
795 // No-throw
optional(none_t none_)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
optional(argument_type val)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
optional(rval_reference_type val)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
optional(bool cond,argument_type val)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>
optional(optional<U> const & rhs,typename boost::enable_if<optional_detail::is_optional_constructible<T,U const &>>::type * =0)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>
optional(optional<U> && rhs,typename boost::enable_if<optional_detail::is_optional_constructible<T,U>>::type * =0)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>
optional(Expr && expr,BOOST_DEDUCED_TYPENAME boost::enable_if<optional_detail::is_optional_val_init_candidate<T,Expr>>::type * =0)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>
optional(Expr const & 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
optional(optional const & rhs)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 )
BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)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
~optional()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
operator =(Expr && expr)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>
operator =(Expr const & 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>
operator =(optional<U> const & rhs)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>
operator =(optional<U> && rhs)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)
operator =(optional const & rhs)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)
operator =(optional && rhs)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
operator =(T_ && val)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
operator =(argument_type val)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)
operator =(rval_reference_type val)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)
operator =(none_t none_)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>
emplace(Args &&...args)1004 void emplace ( Args&&... args )
1005 {
1006 this->emplace_assign( boost::forward<Args>(args)... );
1007 }
1008
1009 template<class... Args>
optional(in_place_init_t,Args &&...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>
optional(in_place_init_if_t,bool cond,Args &&...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>
emplace(Arg && arg)1021 void emplace ( Arg&& arg )
1022 {
1023 this->emplace_assign( boost::forward<Arg>(arg) );
1024 }
1025
emplace()1026 void emplace ()
1027 {
1028 this->emplace_assign();
1029 }
1030
1031 template<class Args>
optional(in_place_init_t,Args && args)1032 explicit optional ( in_place_init_t, Args&& args )
1033 : base( in_place_init, boost::forward<Args>(args) )
1034 {}
1035
optional(in_place_init_t)1036 explicit optional ( in_place_init_t )
1037 : base( in_place_init )
1038 {}
1039
1040 template<class Args>
optional(in_place_init_if_t,bool cond,Args && 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
optional(in_place_init_if_t,bool cond)1045 explicit optional ( in_place_init_if_t, bool cond )
1046 : base( in_place_init_if, cond )
1047 {}
1048 #else
1049 template<class Arg>
emplace(const Arg & arg)1050 void emplace ( const Arg& arg )
1051 {
1052 this->emplace_assign( arg );
1053 }
1054
1055 template<class Arg>
emplace(Arg & arg)1056 void emplace ( Arg& arg )
1057 {
1058 this->emplace_assign( arg );
1059 }
1060
emplace()1061 void emplace ()
1062 {
1063 this->emplace_assign();
1064 }
1065
1066 template<class Arg>
optional(in_place_init_t,const Arg & arg)1067 explicit optional ( in_place_init_t, const Arg& arg )
1068 : base( in_place_init, arg )
1069 {}
1070
1071 template<class Arg>
optional(in_place_init_t,Arg & arg)1072 explicit optional ( in_place_init_t, Arg& arg )
1073 : base( in_place_init, arg )
1074 {}
1075
optional(in_place_init_t)1076 explicit optional ( in_place_init_t )
1077 : base( in_place_init )
1078 {}
1079
1080 template<class Arg>
optional(in_place_init_if_t,bool cond,const Arg & 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>
optional(in_place_init_if_t,bool cond,Arg & arg)1086 explicit optional ( in_place_init_if_t, bool cond, Arg& arg )
1087 : base( in_place_init_if, cond, arg )
1088 {}
1089
optional(in_place_init_if_t,bool cond)1090 explicit optional ( in_place_init_if_t, bool cond )
1091 : base( in_place_init_if, cond )
1092 {}
1093 #endif
1094
swap(optional & arg)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
get() const1106 reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
get()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
get_value_or(reference_const_type v) const1110 reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
get_value_or(reference_type 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
operator ->() const1116 pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
operator ->()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)
operator *() const1123 reference_const_type operator *() const& { return this->get() ; }
operator *()1124 reference_type operator *() & { return this->get() ; }
operator *()1125 reference_type_of_temporary_wrapper operator *() && { return boost::move(this->get()) ; }
1126 #else
operator *() const1127 reference_const_type operator *() const { return this->get() ; }
operator *()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)
value() const1132 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
value()1140 reference_type value() &
1141 {
1142 if (this->is_initialized())
1143 return this->get() ;
1144 else
1145 throw_exception(bad_optional_access());
1146 }
1147
value()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
value() const1157 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
value()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>
value_or(U && v) const1177 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>
value_or(U && v)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>
value_or(U && v) const1195 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>
value_or(U const & v) const1204 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>
value_or(U & v) const1213 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>
value_or_eval(F f) const1225 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>
value_or_eval(F 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>
value_or_eval(F f) const1243 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
operator !() const1252 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
make_optional(T const & v)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
make_optional(bool cond,T const & v)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
get(optional<T> const & opt)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
get(optional<T> & opt)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
get(optional<T> const * opt)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
get(optional<T> * opt)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
get_optional_value_or(optional<T> const & opt,BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v)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
get_optional_value_or(optional<T> & opt,BOOST_DEDUCED_TYPENAME optional<T>::reference_type v)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
get_pointer(optional<T> const & opt)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
get_pointer(optional<T> & opt)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>&
operator <<(std::basic_ostream<CharType,CharTrait> & os,optional_detail::optional_tag const &)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