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