imgtools/imglib/boostlibrary/boost/optional/optional.hpp
changeset 600 6d08f4a05d93
equal deleted inserted replaced
599:fa7a3cc6effd 600:6d08f4a05d93
       
     1 // Copyright (C) 2003, Fernando Luis Cacciola Carballal.
       
     2 //
       
     3 // Use, modification, and distribution is subject to the Boost Software
       
     4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
       
     5 // http://www.boost.org/LICENSE_1_0.txt)
       
     6 //
       
     7 // See http://www.boost.org/lib/optional for documentation.
       
     8 //
       
     9 // You are welcome to contact the author at:
       
    10 //  fernando_cacciola@hotmail.com
       
    11 //
       
    12 #ifndef BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
       
    13 #define BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
       
    14 
       
    15 #include<new>
       
    16 #include<algorithm>
       
    17 
       
    18 #include "boost/config.hpp"
       
    19 #include "boost/assert.hpp"
       
    20 #include "boost/type.hpp"
       
    21 #include "boost/type_traits/alignment_of.hpp"
       
    22 #include "boost/type_traits/type_with_alignment.hpp"
       
    23 #include "boost/type_traits/remove_reference.hpp"
       
    24 #include "boost/type_traits/is_reference.hpp"
       
    25 #include "boost/mpl/if.hpp"
       
    26 #include "boost/mpl/bool.hpp"
       
    27 #include "boost/mpl/not.hpp"
       
    28 #include "boost/detail/reference_content.hpp"
       
    29 #include "boost/none.hpp"
       
    30 #include "boost/utility/compare_pointees.hpp"
       
    31 
       
    32 #include "boost/optional/optional_fwd.hpp"
       
    33 
       
    34 #if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
       
    35 // VC6.0 has the following bug:
       
    36 //   When a templated assignment operator exist, an implicit conversion
       
    37 //   constructing an optional<T> is used when assigment of the form:
       
    38 //     optional<T> opt ; opt = T(...);
       
    39 //   is compiled.
       
    40 //   However, optional's ctor is _explicit_ and the assignemt shouldn't compile.
       
    41 //   Therefore, for VC6.0 templated assignment is disabled.
       
    42 //
       
    43 #define BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
       
    44 #endif
       
    45 
       
    46 #if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
       
    47 // VC7.0 has the following bug:
       
    48 //   When both a non-template and a template copy-ctor exist
       
    49 //   and the templated version is made 'explicit', the explicit is also
       
    50 //   given to the non-templated version, making the class non-implicitely-copyable.
       
    51 //
       
    52 #define BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
       
    53 #endif
       
    54 
       
    55 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION,<=700)
       
    56 // AFAICT only VC7.1 correctly resolves the overload set
       
    57 // that includes the in-place factory taking functions,
       
    58 // so for the other VC versions, in-place factory support
       
    59 // is disabled
       
    60 #define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
       
    61 #endif
       
    62 
       
    63 #if BOOST_WORKAROUND(__BORLANDC__, <= 0x551)
       
    64 // BCB (5.5.1) cannot parse the nested template struct in an inplace factory.
       
    65 #define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
       
    66 #endif
       
    67 
       
    68 #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) \
       
    69     && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581) )
       
    70 // BCB (up to 5.64) has the following bug:
       
    71 //   If there is a member function/operator template of the form
       
    72 //     template<class Expr> mfunc( Expr expr ) ;
       
    73 //   some calls are resolved to this even if there are other better matches.
       
    74 //   The effect of this bug is that calls to converting ctors and assignments
       
    75 //   are incrorrectly sink to this general catch-all member function template as shown above.
       
    76 #define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
       
    77 #endif
       
    78 
       
    79 // Daniel Wallin discovered that bind/apply.hpp badly interacts with the apply<>
       
    80 // member template of a factory as used in the optional<> implementation.
       
    81 // He proposed this simple fix which is to move the call to apply<> outside
       
    82 // namespace boost.
       
    83 namespace boost_optional_detail
       
    84 {
       
    85   template <class T, class Factory>
       
    86   void construct(Factory const& factory, void* address)
       
    87   {
       
    88     factory.BOOST_NESTED_TEMPLATE apply<T>(address);
       
    89   }
       
    90 }
       
    91 
       
    92 
       
    93 namespace boost {
       
    94 
       
    95 class in_place_factory_base ;
       
    96 class typed_in_place_factory_base ;
       
    97 
       
    98 namespace optional_detail {
       
    99 
       
   100 // This local class is used instead of that in "aligned_storage.hpp"
       
   101 // because I've found the 'official' class to ICE BCB5.5
       
   102 // when some types are used with optional<>
       
   103 // (due to sizeof() passed down as a non-type template parameter)
       
   104 template <class T>
       
   105 class aligned_storage
       
   106 {
       
   107     // Borland ICEs if unnamed unions are used for this!
       
   108     union dummy_u
       
   109     {
       
   110         char data[ sizeof(T) ];
       
   111         BOOST_DEDUCED_TYPENAME type_with_alignment<
       
   112           ::boost::alignment_of<T>::value >::type aligner_;
       
   113     } dummy_ ;
       
   114 
       
   115   public:
       
   116 
       
   117     void const* address() const { return &dummy_.data[0]; }
       
   118     void      * address()       { return &dummy_.data[0]; }
       
   119 } ;
       
   120 
       
   121 template<class T>
       
   122 struct types_when_isnt_ref
       
   123 {
       
   124   typedef T const& reference_const_type ;
       
   125   typedef T &      reference_type ;
       
   126   typedef T const* pointer_const_type ;
       
   127   typedef T *      pointer_type ;
       
   128   typedef T const& argument_type ;
       
   129 } ;
       
   130 template<class T>
       
   131 struct types_when_is_ref
       
   132 {
       
   133   typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type raw_type ;
       
   134 
       
   135   typedef raw_type& reference_const_type ;
       
   136   typedef raw_type& reference_type ;
       
   137   typedef raw_type* pointer_const_type ;
       
   138   typedef raw_type* pointer_type ;
       
   139   typedef raw_type& argument_type ;
       
   140 } ;
       
   141 
       
   142 struct optional_tag {} ;
       
   143 
       
   144 template<class T>
       
   145 class optional_base : public optional_tag
       
   146 {
       
   147   private :
       
   148 
       
   149     typedef
       
   150 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
       
   151     BOOST_DEDUCED_TYPENAME
       
   152 #endif 
       
   153     ::boost::detail::make_reference_content<T>::type internal_type ;
       
   154 
       
   155     typedef aligned_storage<internal_type> storage_type ;
       
   156 
       
   157     typedef types_when_isnt_ref<T> types_when_not_ref ;
       
   158     typedef types_when_is_ref<T>   types_when_ref   ;
       
   159 
       
   160     typedef optional_base<T> this_type ;
       
   161 
       
   162   protected :
       
   163 
       
   164     typedef T value_type ;
       
   165 
       
   166     typedef mpl::true_  is_reference_tag ;
       
   167     typedef mpl::false_ is_not_reference_tag ;
       
   168 
       
   169     typedef BOOST_DEDUCED_TYPENAME is_reference<T>::type is_reference_predicate ;
       
   170 
       
   171     typedef BOOST_DEDUCED_TYPENAME mpl::if_<is_reference_predicate,types_when_ref,types_when_not_ref>::type types ;
       
   172 
       
   173     typedef bool (this_type::*unspecified_bool_type)() const;
       
   174 
       
   175     typedef BOOST_DEDUCED_TYPENAME types::reference_type       reference_type ;
       
   176     typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ;
       
   177     typedef BOOST_DEDUCED_TYPENAME types::pointer_type         pointer_type ;
       
   178     typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type   pointer_const_type ;
       
   179     typedef BOOST_DEDUCED_TYPENAME types::argument_type        argument_type ;
       
   180 
       
   181     // Creates an optional<T> uninitialized.
       
   182     // No-throw
       
   183     optional_base()
       
   184       :
       
   185       m_initialized(false) {}
       
   186 
       
   187     // Creates an optional<T> uninitialized.
       
   188     // No-throw
       
   189     optional_base ( none_t )
       
   190       :
       
   191       m_initialized(false) {}
       
   192 
       
   193     // Creates an optional<T> initialized with 'val'.
       
   194     // Can throw if T::T(T const&) does
       
   195     optional_base ( argument_type val )
       
   196       :
       
   197       m_initialized(false)
       
   198     {
       
   199       construct(val);
       
   200     }
       
   201     
       
   202     // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>.
       
   203     // Can throw if T::T(T const&) does
       
   204     optional_base ( bool cond, argument_type val )
       
   205       :
       
   206       m_initialized(false)
       
   207     {
       
   208       if ( cond )
       
   209         construct(val);
       
   210     }
       
   211 
       
   212     // Creates a deep copy of another optional<T>
       
   213     // Can throw if T::T(T const&) does
       
   214     optional_base ( optional_base const& rhs )
       
   215       :
       
   216       m_initialized(false)
       
   217     {
       
   218       if ( rhs.is_initialized() )
       
   219         construct(rhs.get_impl());
       
   220     }
       
   221 
       
   222 
       
   223     // This is used for both converting and in-place constructions.
       
   224     // Derived classes use the 'tag' to select the appropriate
       
   225     // implementation (the correct 'construct()' overload)
       
   226     template<class Expr>
       
   227     explicit optional_base ( Expr const& expr, Expr const* tag )
       
   228       :
       
   229       m_initialized(false)
       
   230     {
       
   231       construct(expr,tag);
       
   232     }
       
   233 
       
   234 
       
   235 
       
   236     // No-throw (assuming T::~T() doesn't)
       
   237     ~optional_base() { destroy() ; }
       
   238 
       
   239     // Assigns from another optional<T> (deep-copies the rhs value)
       
   240     void assign ( optional_base const& rhs )
       
   241     {
       
   242       if (is_initialized())
       
   243       {
       
   244         if ( rhs.is_initialized() )
       
   245              assign_value(rhs.get_impl(), is_reference_predicate() );
       
   246         else destroy();
       
   247       }
       
   248       else
       
   249       {
       
   250         if ( rhs.is_initialized() )
       
   251           construct(rhs.get_impl());
       
   252       }
       
   253     }
       
   254 
       
   255     // Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
       
   256     template<class U>
       
   257     void assign ( optional<U> const& rhs )
       
   258     {
       
   259       if (is_initialized())
       
   260       {
       
   261         if ( rhs.is_initialized() )
       
   262              assign_value(static_cast<value_type>(rhs.get()), is_reference_predicate() );
       
   263         else destroy();
       
   264       }
       
   265       else
       
   266       {
       
   267         if ( rhs.is_initialized() )
       
   268           construct(static_cast<value_type>(rhs.get()));
       
   269       }
       
   270     }
       
   271 
       
   272     // Assigns from a T (deep-copies the rhs value)
       
   273     void assign ( argument_type val )
       
   274     {
       
   275       if (is_initialized())
       
   276            assign_value(val, is_reference_predicate() );
       
   277       else construct(val);
       
   278     }
       
   279 
       
   280     // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
       
   281     // No-throw (assuming T::~T() doesn't)
       
   282     void assign ( none_t ) { destroy(); }
       
   283 
       
   284 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
       
   285     template<class Expr>
       
   286     void assign_expr ( Expr const& expr, Expr const* tag )
       
   287       {
       
   288         if (is_initialized())
       
   289              assign_expr_to_initialized(expr,tag);
       
   290         else construct(expr,tag);
       
   291       }
       
   292 #endif
       
   293 
       
   294   public :
       
   295 
       
   296     // Destroys the current value, if any, leaving this UNINITIALIZED
       
   297     // No-throw (assuming T::~T() doesn't)
       
   298     void reset() { destroy(); }
       
   299 
       
   300     // Replaces the current value -if any- with 'val'
       
   301     void reset ( argument_type val ) { assign(val); }
       
   302 
       
   303     // Returns a pointer to the value if this is initialized, otherwise,
       
   304     // returns NULL.
       
   305     // No-throw
       
   306     pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
       
   307     pointer_type       get_ptr()       { return m_initialized ? get_ptr_impl() : 0 ; }
       
   308 
       
   309     bool is_initialized() const { return m_initialized ; }
       
   310 
       
   311   protected :
       
   312 
       
   313     void construct ( argument_type val )
       
   314      {
       
   315        new (m_storage.address()) internal_type(val) ;
       
   316        m_initialized = true ;
       
   317      }
       
   318 
       
   319 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
       
   320     // Constructs in-place using the given factory
       
   321     template<class Expr>
       
   322     void construct ( Expr const& factory, in_place_factory_base const* )
       
   323      {
       
   324        BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
       
   325        boost_optional_detail::construct<value_type>(factory, m_storage.address());
       
   326        m_initialized = true ;
       
   327      }
       
   328 
       
   329     // Constructs in-place using the given typed factory
       
   330     template<class Expr>
       
   331     void construct ( Expr const& factory, typed_in_place_factory_base const* )
       
   332      {
       
   333        BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
       
   334        factory.apply(m_storage.address()) ;
       
   335        m_initialized = true ;
       
   336      }
       
   337 
       
   338     template<class Expr>
       
   339     void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag )
       
   340      {
       
   341        destroy();
       
   342        construct(factory,tag);
       
   343      }
       
   344 
       
   345     // Constructs in-place using the given typed factory
       
   346     template<class Expr>
       
   347     void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag )
       
   348      {
       
   349        destroy();
       
   350        construct(factory,tag);
       
   351      }
       
   352 #endif
       
   353 
       
   354     // Constructs using any expression implicitely convertible to the single argument
       
   355     // of a one-argument T constructor.
       
   356     // Converting constructions of optional<T> from optional<U> uses this function with
       
   357     // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
       
   358     template<class Expr>
       
   359     void construct ( Expr const& expr, void const* )
       
   360      {
       
   361        new (m_storage.address()) internal_type(expr) ;
       
   362        m_initialized = true ;
       
   363      }
       
   364 
       
   365     // Assigns using a form any expression implicitely convertible to the single argument
       
   366     // of a T's assignment operator.
       
   367     // Converting assignments of optional<T> from optional<U> uses this function with
       
   368     // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
       
   369     template<class Expr>
       
   370     void assign_expr_to_initialized ( Expr const& expr, void const* )
       
   371      {
       
   372        assign_value(expr, is_reference_predicate());
       
   373      }
       
   374 
       
   375 #ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
       
   376     // BCB5.64 (and probably lower versions) workaround.
       
   377     //   The in-place factories are supported by means of catch-all constructors
       
   378     //   and assignment operators (the functions are parameterized in terms of
       
   379     //   an arbitrary 'Expr' type)
       
   380     //   This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U>
       
   381     //   to the 'Expr'-taking functions even though explicit overloads are present for them.
       
   382     //   Thus, the following overload is needed to properly handle the case when the 'lhs'
       
   383     //   is another optional.
       
   384     //
       
   385     // For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error
       
   386     // instead of choosing the wrong overload
       
   387     //
       
   388     // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
       
   389     template<class Expr>
       
   390     void construct ( Expr const& expr, optional_tag const* )
       
   391      {
       
   392        if ( expr.is_initialized() )
       
   393        {
       
   394          // An exception can be thrown here.
       
   395          // It it happens, THIS will be left uninitialized.
       
   396          new (m_storage.address()) internal_type(expr.get()) ;
       
   397          m_initialized = true ;
       
   398        }
       
   399      }
       
   400 #endif
       
   401 
       
   402     void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; }
       
   403     void assign_value ( argument_type val, is_reference_tag     ) { construct(val); }
       
   404 
       
   405     void destroy()
       
   406     {
       
   407       if ( m_initialized )
       
   408         destroy_impl(is_reference_predicate()) ;
       
   409     }
       
   410 
       
   411     unspecified_bool_type safe_bool() const { return m_initialized ? &this_type::is_initialized : 0 ; }
       
   412 
       
   413     reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; }
       
   414     reference_type       get_impl()       { return dereference(get_object(), is_reference_predicate() ) ; }
       
   415 
       
   416     pointer_const_type get_ptr_impl() const { return cast_ptr(get_object(), is_reference_predicate() ) ; }
       
   417     pointer_type       get_ptr_impl()       { return cast_ptr(get_object(), is_reference_predicate() ) ; }
       
   418 
       
   419   private :
       
   420 
       
   421     // internal_type can be either T or reference_content<T>
       
   422     internal_type const* get_object() const { return static_cast<internal_type const*>(m_storage.address()); }
       
   423     internal_type *      get_object()       { return static_cast<internal_type *>     (m_storage.address()); }
       
   424 
       
   425     // reference_content<T> lacks an implicit conversion to T&, so the following is needed to obtain a proper reference.
       
   426     reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; }
       
   427     reference_type       dereference( internal_type*       p, is_not_reference_tag )       { return *p ; }
       
   428     reference_const_type dereference( internal_type const* p, is_reference_tag     ) const { return p->get() ; }
       
   429     reference_type       dereference( internal_type*       p, is_reference_tag     )       { return p->get() ; }
       
   430 
       
   431 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
       
   432     void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; }
       
   433 #else
       
   434     void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->T::~T() ; m_initialized = false ; }
       
   435 #endif
       
   436 
       
   437     void destroy_impl ( is_reference_tag     ) { m_initialized = false ; }
       
   438 
       
   439     // If T is of reference type, trying to get a pointer to the held value must result in a compile-time error.
       
   440     // Decent compilers should disallow conversions from reference_content<T>* to T*, but just in case,
       
   441     // the following olverloads are used to filter out the case and guarantee an error in case of T being a reference.
       
   442     pointer_const_type cast_ptr( internal_type const* p, is_not_reference_tag ) const { return p ; }
       
   443     pointer_type       cast_ptr( internal_type *      p, is_not_reference_tag )       { return p ; }
       
   444     pointer_const_type cast_ptr( internal_type const* p, is_reference_tag     ) const { return &p->get() ; }
       
   445     pointer_type       cast_ptr( internal_type *      p, is_reference_tag     )       { return &p->get() ; }
       
   446 
       
   447     bool m_initialized ;
       
   448     storage_type m_storage ;
       
   449 } ;
       
   450 
       
   451 } // namespace optional_detail
       
   452 
       
   453 template<class T>
       
   454 class optional : public optional_detail::optional_base<T>
       
   455 {
       
   456     typedef optional_detail::optional_base<T> base ;
       
   457 
       
   458     typedef BOOST_DEDUCED_TYPENAME base::unspecified_bool_type  unspecified_bool_type ;
       
   459 
       
   460   public :
       
   461 
       
   462     typedef optional<T> this_type ;
       
   463 
       
   464     typedef BOOST_DEDUCED_TYPENAME base::value_type           value_type ;
       
   465     typedef BOOST_DEDUCED_TYPENAME base::reference_type       reference_type ;
       
   466     typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
       
   467     typedef BOOST_DEDUCED_TYPENAME base::pointer_type         pointer_type ;
       
   468     typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type   pointer_const_type ;
       
   469     typedef BOOST_DEDUCED_TYPENAME base::argument_type        argument_type ;
       
   470 
       
   471     // Creates an optional<T> uninitialized.
       
   472     // No-throw
       
   473     optional() : base() {}
       
   474 
       
   475     // Creates an optional<T> uninitialized.
       
   476     // No-throw
       
   477     optional( none_t none_ ) : base(none_) {}
       
   478 
       
   479     // Creates an optional<T> initialized with 'val'.
       
   480     // Can throw if T::T(T const&) does
       
   481     optional ( argument_type val ) : base(val) {}
       
   482 
       
   483     // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
       
   484     // Can throw if T::T(T const&) does
       
   485     optional ( bool cond, argument_type val ) : base(cond,val) {}
       
   486 
       
   487 #ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
       
   488     // NOTE: MSVC needs templated versions first
       
   489 
       
   490     // Creates a deep copy of another convertible optional<U>
       
   491     // Requires a valid conversion from U to T.
       
   492     // Can throw if T::T(U const&) does
       
   493     template<class U>
       
   494     explicit optional ( optional<U> const& rhs )
       
   495       :
       
   496       base()
       
   497     {
       
   498       if ( rhs.is_initialized() )
       
   499         this->construct(rhs.get());
       
   500     }
       
   501 #endif
       
   502 
       
   503 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
       
   504     // Creates an optional<T> with an expression which can be either
       
   505     //  (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
       
   506     //  (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
       
   507     //  (c) Any expression implicitely convertible to the single type
       
   508     //      of a one-argument T's constructor.
       
   509     //  (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
       
   510     //       even though explicit overloads are present for these.
       
   511     // Depending on the above some T ctor is called.
       
   512     // Can throw is the resolved T ctor throws.
       
   513     template<class Expr>
       
   514     explicit optional ( Expr const& expr ) : base(expr,&expr) {}
       
   515 #endif
       
   516 
       
   517     // Creates a deep copy of another optional<T>
       
   518     // Can throw if T::T(T const&) does
       
   519     optional ( optional const& rhs ) : base(rhs) {}
       
   520 
       
   521    // No-throw (assuming T::~T() doesn't)
       
   522     ~optional() {}
       
   523 
       
   524 #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
       
   525     // Assigns from an expression. See corresponding constructor.
       
   526     // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
       
   527     template<class Expr>
       
   528     optional& operator= ( Expr expr )
       
   529       {
       
   530         this->assign_expr(expr,&expr);
       
   531         return *this ;
       
   532       }
       
   533 #endif
       
   534 
       
   535 
       
   536 #ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
       
   537     // Assigns from another convertible optional<U> (converts && deep-copies the rhs value)
       
   538     // Requires a valid conversion from U to T.
       
   539     // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
       
   540     template<class U>
       
   541     optional& operator= ( optional<U> const& rhs )
       
   542       {
       
   543         this->assign(rhs);
       
   544         return *this ;
       
   545       }
       
   546 #endif
       
   547 
       
   548     // Assigns from another optional<T> (deep-copies the rhs value)
       
   549     // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
       
   550     //  (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
       
   551     optional& operator= ( optional const& rhs )
       
   552       {
       
   553         this->assign( rhs ) ;
       
   554         return *this ;
       
   555       }
       
   556 
       
   557     // Assigns from a T (deep-copies the rhs value)
       
   558     // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
       
   559     optional& operator= ( argument_type val )
       
   560       {
       
   561         this->assign( val ) ;
       
   562         return *this ;
       
   563       }
       
   564 
       
   565     // Assigns from a "none"
       
   566     // Which destroys the current value, if any, leaving this UNINITIALIZED
       
   567     // No-throw (assuming T::~T() doesn't)
       
   568     optional& operator= ( none_t none_ )
       
   569       {
       
   570         this->assign( none_ ) ;
       
   571         return *this ;
       
   572       }
       
   573 
       
   574     // Returns a reference to the value if this is initialized, otherwise,
       
   575     // the behaviour is UNDEFINED
       
   576     // No-throw
       
   577     reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
       
   578     reference_type       get()       { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
       
   579 
       
   580     // Returns a copy of the value if this is initialized, 'v' otherwise
       
   581     reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
       
   582     reference_type       get_value_or ( reference_type       v )       { return this->is_initialized() ? get() : v ; }
       
   583     
       
   584     // Returns a pointer to the value if this is initialized, otherwise,
       
   585     // the behaviour is UNDEFINED
       
   586     // No-throw
       
   587     pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
       
   588     pointer_type       operator->()       { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
       
   589 
       
   590     // Returns a reference to the value if this is initialized, otherwise,
       
   591     // the behaviour is UNDEFINED
       
   592     // No-throw
       
   593     reference_const_type operator *() const { return this->get() ; }
       
   594     reference_type       operator *()       { return this->get() ; }
       
   595 
       
   596     // implicit conversion to "bool"
       
   597     // No-throw
       
   598     operator unspecified_bool_type() const { return this->safe_bool() ; }
       
   599 
       
   600        // This is provided for those compilers which don't like the conversion to bool
       
   601        // on some contexts.
       
   602        bool operator!() const { return !this->is_initialized() ; }
       
   603 } ;
       
   604 
       
   605 // Returns optional<T>(v)
       
   606 template<class T> 
       
   607 inline 
       
   608 optional<T> make_optional ( T const& v  )
       
   609 {
       
   610   return optional<T>(v);
       
   611 }
       
   612 
       
   613 // Returns optional<T>(cond,v)
       
   614 template<class T> 
       
   615 inline 
       
   616 optional<T> make_optional ( bool cond, T const& v )
       
   617 {
       
   618   return optional<T>(cond,v);
       
   619 }
       
   620 
       
   621 // Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
       
   622 // No-throw
       
   623 template<class T>
       
   624 inline
       
   625 BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
       
   626 get ( optional<T> const& opt )
       
   627 {
       
   628   return opt.get() ;
       
   629 }
       
   630 
       
   631 template<class T>
       
   632 inline
       
   633 BOOST_DEDUCED_TYPENAME optional<T>::reference_type
       
   634 get ( optional<T>& opt )
       
   635 {
       
   636   return opt.get() ;
       
   637 }
       
   638 
       
   639 // Returns a pointer to the value if this is initialized, otherwise, returns NULL.
       
   640 // No-throw
       
   641 template<class T>
       
   642 inline
       
   643 BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
       
   644 get ( optional<T> const* opt )
       
   645 {
       
   646   return opt->get_ptr() ;
       
   647 }
       
   648 
       
   649 template<class T>
       
   650 inline
       
   651 BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
       
   652 get ( optional<T>* opt )
       
   653 {
       
   654   return opt->get_ptr() ;
       
   655 }
       
   656 
       
   657 // Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
       
   658 // No-throw
       
   659 template<class T>
       
   660 inline
       
   661 BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
       
   662 get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v )
       
   663 {
       
   664   return opt.get_value_or(v) ;
       
   665 }
       
   666 
       
   667 template<class T>
       
   668 inline
       
   669 BOOST_DEDUCED_TYPENAME optional<T>::reference_type
       
   670 get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v )
       
   671 {
       
   672   return opt.get_value_or(v) ;
       
   673 }
       
   674 
       
   675 // Returns a pointer to the value if this is initialized, otherwise, returns NULL.
       
   676 // No-throw
       
   677 template<class T>
       
   678 inline
       
   679 BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
       
   680 get_pointer ( optional<T> const& opt )
       
   681 {
       
   682   return opt.get_ptr() ;
       
   683 }
       
   684 
       
   685 template<class T>
       
   686 inline
       
   687 BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
       
   688 get_pointer ( optional<T>& opt )
       
   689 {
       
   690   return opt.get_ptr() ;
       
   691 }
       
   692 
       
   693 // optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values).
       
   694 // WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead.
       
   695 
       
   696 
       
   697 //
       
   698 // optional<T> vs optional<T> cases
       
   699 //
       
   700 
       
   701 template<class T>
       
   702 inline
       
   703 bool operator == ( optional<T> const& x, optional<T> const& y )
       
   704 { return equal_pointees(x,y); }
       
   705 
       
   706 template<class T>
       
   707 inline
       
   708 bool operator < ( optional<T> const& x, optional<T> const& y )
       
   709 { return less_pointees(x,y); }
       
   710 
       
   711 template<class T>
       
   712 inline
       
   713 bool operator != ( optional<T> const& x, optional<T> const& y )
       
   714 { return !( x == y ) ; }
       
   715 
       
   716 template<class T>
       
   717 inline
       
   718 bool operator > ( optional<T> const& x, optional<T> const& y )
       
   719 { return y < x ; }
       
   720 
       
   721 template<class T>
       
   722 inline
       
   723 bool operator <= ( optional<T> const& x, optional<T> const& y )
       
   724 { return !( y < x ) ; }
       
   725 
       
   726 template<class T>
       
   727 inline
       
   728 bool operator >= ( optional<T> const& x, optional<T> const& y )
       
   729 { return !( x < y ) ; }
       
   730 
       
   731 
       
   732 //
       
   733 // optional<T> vs T cases
       
   734 //
       
   735 template<class T>
       
   736 inline
       
   737 bool operator == ( optional<T> const& x, T const& y )
       
   738 { return equal_pointees(x, optional<T>(y)); }
       
   739 
       
   740 template<class T>
       
   741 inline
       
   742 bool operator < ( optional<T> const& x, T const& y )
       
   743 { return less_pointees(x, optional<T>(y)); }
       
   744 
       
   745 template<class T>
       
   746 inline
       
   747 bool operator != ( optional<T> const& x, T const& y )
       
   748 { return !( x == y ) ; }
       
   749 
       
   750 template<class T>
       
   751 inline
       
   752 bool operator > ( optional<T> const& x, T const& y )
       
   753 { return y < x ; }
       
   754 
       
   755 template<class T>
       
   756 inline
       
   757 bool operator <= ( optional<T> const& x, T const& y )
       
   758 { return !( y < x ) ; }
       
   759 
       
   760 template<class T>
       
   761 inline
       
   762 bool operator >= ( optional<T> const& x, T const& y )
       
   763 { return !( x < y ) ; }
       
   764 
       
   765 //
       
   766 // T vs optional<T> cases
       
   767 //
       
   768 
       
   769 template<class T>
       
   770 inline
       
   771 bool operator == ( T const& x, optional<T> const& y )
       
   772 { return equal_pointees( optional<T>(x), y ); }
       
   773 
       
   774 template<class T>
       
   775 inline
       
   776 bool operator < ( T const& x, optional<T> const& y )
       
   777 { return less_pointees( optional<T>(x), y ); }
       
   778 
       
   779 template<class T>
       
   780 inline
       
   781 bool operator != ( T const& x, optional<T> const& y )
       
   782 { return !( x == y ) ; }
       
   783 
       
   784 template<class T>
       
   785 inline
       
   786 bool operator > ( T const& x, optional<T> const& y )
       
   787 { return y < x ; }
       
   788 
       
   789 template<class T>
       
   790 inline
       
   791 bool operator <= ( T const& x, optional<T> const& y )
       
   792 { return !( y < x ) ; }
       
   793 
       
   794 template<class T>
       
   795 inline
       
   796 bool operator >= ( T const& x, optional<T> const& y )
       
   797 { return !( x < y ) ; }
       
   798 
       
   799 
       
   800 //
       
   801 // optional<T> vs none cases
       
   802 //
       
   803 
       
   804 template<class T>
       
   805 inline
       
   806 bool operator == ( optional<T> const& x, none_t )
       
   807 { return equal_pointees(x, optional<T>() ); }
       
   808 
       
   809 template<class T>
       
   810 inline
       
   811 bool operator < ( optional<T> const& x, none_t )
       
   812 { return less_pointees(x,optional<T>() ); }
       
   813 
       
   814 template<class T>
       
   815 inline
       
   816 bool operator != ( optional<T> const& x, none_t y )
       
   817 { return !( x == y ) ; }
       
   818 
       
   819 template<class T>
       
   820 inline
       
   821 bool operator > ( optional<T> const& x, none_t y )
       
   822 { return y < x ; }
       
   823 
       
   824 template<class T>
       
   825 inline
       
   826 bool operator <= ( optional<T> const& x, none_t y )
       
   827 { return !( y < x ) ; }
       
   828 
       
   829 template<class T>
       
   830 inline
       
   831 bool operator >= ( optional<T> const& x, none_t y )
       
   832 { return !( x < y ) ; }
       
   833 
       
   834 //
       
   835 // none vs optional<T> cases
       
   836 //
       
   837 
       
   838 template<class T>
       
   839 inline
       
   840 bool operator == ( none_t x, optional<T> const& y )
       
   841 { return equal_pointees(optional<T>() ,y); }
       
   842 
       
   843 template<class T>
       
   844 inline
       
   845 bool operator < ( none_t x, optional<T> const& y )
       
   846 { return less_pointees(optional<T>() ,y); }
       
   847 
       
   848 template<class T>
       
   849 inline
       
   850 bool operator != ( none_t x, optional<T> const& y )
       
   851 { return !( x == y ) ; }
       
   852 
       
   853 template<class T>
       
   854 inline
       
   855 bool operator > ( none_t x, optional<T> const& y )
       
   856 { return y < x ; }
       
   857 
       
   858 template<class T>
       
   859 inline
       
   860 bool operator <= ( none_t x, optional<T> const& y )
       
   861 { return !( y < x ) ; }
       
   862 
       
   863 template<class T>
       
   864 inline
       
   865 bool operator >= ( none_t x, optional<T> const& y )
       
   866 { return !( x < y ) ; }
       
   867 
       
   868 //
       
   869 // The following swap implementation follows the GCC workaround as found in
       
   870 //  "boost/detail/compressed_pair.hpp"
       
   871 //
       
   872 namespace optional_detail {
       
   873 
       
   874 // GCC < 3.2 gets the using declaration at namespace scope (FLC, DWA)
       
   875 #if BOOST_WORKAROUND(__GNUC__, < 3)                             \
       
   876     || BOOST_WORKAROUND(__GNUC__, == 3) && __GNUC_MINOR__ <= 2
       
   877    using std::swap;
       
   878 #define BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE
       
   879 #endif
       
   880 
       
   881 // optional's swap:
       
   882 // If both are initialized, calls swap(T&, T&). If this swap throws, both will remain initialized but their values are now unspecified.
       
   883 // If only one is initialized, calls U.reset(*I), THEN I.reset().
       
   884 // If U.reset(*I) throws, both are left UNCHANGED (U is kept uinitialized and I is never reset)
       
   885 // If both are uninitialized, do nothing (no-throw)
       
   886 template<class T>
       
   887 inline
       
   888 void optional_swap ( optional<T>& x, optional<T>& y )
       
   889 {
       
   890   if ( !x && !!y )
       
   891   {
       
   892     x.reset(*y);
       
   893     y.reset();
       
   894   }
       
   895   else if ( !!x && !y )
       
   896   {
       
   897     y.reset(*x);
       
   898     x.reset();
       
   899   }
       
   900   else if ( !!x && !!y )
       
   901   {
       
   902 // GCC > 3.2 and all other compilers have the using declaration at function scope (FLC)
       
   903 #ifndef BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE
       
   904     // allow for Koenig lookup
       
   905     using std::swap ;
       
   906 #endif
       
   907     swap(*x,*y);
       
   908   }
       
   909 }
       
   910 
       
   911 } // namespace optional_detail
       
   912 
       
   913 template<class T> inline void swap ( optional<T>& x, optional<T>& y )
       
   914 {
       
   915   optional_detail::optional_swap(x,y);
       
   916 }
       
   917 
       
   918 
       
   919 } // namespace boost
       
   920 
       
   921 #endif
       
   922