epoc32/include/stdapis/boost/optional/optional.hpp
author William Roberts <williamr@symbian.org>
Tue, 16 Mar 2010 16:12:26 +0000
branchSymbian2
changeset 2 2fe1408b6811
permissions -rw-r--r--
Final list of Symbian^2 public API header files
     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