Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/optional/optional.hpp @ 47

Last change on this file since 47 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 28.4 KB
Line 
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.
83namespace 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
93namespace boost {
94
95class in_place_factory_base ;
96class typed_in_place_factory_base ;
97
98namespace 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)
104template <class T>
105class 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
121template<class T>
122struct 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} ;
130template<class T>
131struct 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
142struct optional_tag {} ;
143
144template<class T>
145class 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
453template<class T>
454class 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)
606template<class T> 
607inline 
608optional<T> make_optional ( T const& v  )
609{
610  return optional<T>(v);
611}
612
613// Returns optional<T>(cond,v)
614template<class T> 
615inline 
616optional<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
623template<class T>
624inline
625BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
626get ( optional<T> const& opt )
627{
628  return opt.get() ;
629}
630
631template<class T>
632inline
633BOOST_DEDUCED_TYPENAME optional<T>::reference_type
634get ( 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
641template<class T>
642inline
643BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
644get ( optional<T> const* opt )
645{
646  return opt->get_ptr() ;
647}
648
649template<class T>
650inline
651BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
652get ( 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
659template<class T>
660inline
661BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
662get_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
667template<class T>
668inline
669BOOST_DEDUCED_TYPENAME optional<T>::reference_type
670get_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
677template<class T>
678inline
679BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
680get_pointer ( optional<T> const& opt )
681{
682  return opt.get_ptr() ;
683}
684
685template<class T>
686inline
687BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
688get_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
701template<class T>
702inline
703bool operator == ( optional<T> const& x, optional<T> const& y )
704{ return equal_pointees(x,y); }
705
706template<class T>
707inline
708bool operator < ( optional<T> const& x, optional<T> const& y )
709{ return less_pointees(x,y); }
710
711template<class T>
712inline
713bool operator != ( optional<T> const& x, optional<T> const& y )
714{ return !( x == y ) ; }
715
716template<class T>
717inline
718bool operator > ( optional<T> const& x, optional<T> const& y )
719{ return y < x ; }
720
721template<class T>
722inline
723bool operator <= ( optional<T> const& x, optional<T> const& y )
724{ return !( y < x ) ; }
725
726template<class T>
727inline
728bool operator >= ( optional<T> const& x, optional<T> const& y )
729{ return !( x < y ) ; }
730
731
732//
733// optional<T> vs T cases
734//
735template<class T>
736inline
737bool operator == ( optional<T> const& x, T const& y )
738{ return equal_pointees(x, optional<T>(y)); }
739
740template<class T>
741inline
742bool operator < ( optional<T> const& x, T const& y )
743{ return less_pointees(x, optional<T>(y)); }
744
745template<class T>
746inline
747bool operator != ( optional<T> const& x, T const& y )
748{ return !( x == y ) ; }
749
750template<class T>
751inline
752bool operator > ( optional<T> const& x, T const& y )
753{ return y < x ; }
754
755template<class T>
756inline
757bool operator <= ( optional<T> const& x, T const& y )
758{ return !( y < x ) ; }
759
760template<class T>
761inline
762bool operator >= ( optional<T> const& x, T const& y )
763{ return !( x < y ) ; }
764
765//
766// T vs optional<T> cases
767//
768
769template<class T>
770inline
771bool operator == ( T const& x, optional<T> const& y )
772{ return equal_pointees( optional<T>(x), y ); }
773
774template<class T>
775inline
776bool operator < ( T const& x, optional<T> const& y )
777{ return less_pointees( optional<T>(x), y ); }
778
779template<class T>
780inline
781bool operator != ( T const& x, optional<T> const& y )
782{ return !( x == y ) ; }
783
784template<class T>
785inline
786bool operator > ( T const& x, optional<T> const& y )
787{ return y < x ; }
788
789template<class T>
790inline
791bool operator <= ( T const& x, optional<T> const& y )
792{ return !( y < x ) ; }
793
794template<class T>
795inline
796bool operator >= ( T const& x, optional<T> const& y )
797{ return !( x < y ) ; }
798
799
800//
801// optional<T> vs none cases
802//
803
804template<class T>
805inline
806bool operator == ( optional<T> const& x, none_t )
807{ return equal_pointees(x, optional<T>() ); }
808
809template<class T>
810inline
811bool operator < ( optional<T> const& x, none_t )
812{ return less_pointees(x,optional<T>() ); }
813
814template<class T>
815inline
816bool operator != ( optional<T> const& x, none_t y )
817{ return !( x == y ) ; }
818
819template<class T>
820inline
821bool operator > ( optional<T> const& x, none_t y )
822{ return y < x ; }
823
824template<class T>
825inline
826bool operator <= ( optional<T> const& x, none_t y )
827{ return !( y < x ) ; }
828
829template<class T>
830inline
831bool operator >= ( optional<T> const& x, none_t y )
832{ return !( x < y ) ; }
833
834//
835// none vs optional<T> cases
836//
837
838template<class T>
839inline
840bool operator == ( none_t x, optional<T> const& y )
841{ return equal_pointees(optional<T>() ,y); }
842
843template<class T>
844inline
845bool operator < ( none_t x, optional<T> const& y )
846{ return less_pointees(optional<T>() ,y); }
847
848template<class T>
849inline
850bool operator != ( none_t x, optional<T> const& y )
851{ return !( x == y ) ; }
852
853template<class T>
854inline
855bool operator > ( none_t x, optional<T> const& y )
856{ return y < x ; }
857
858template<class T>
859inline
860bool operator <= ( none_t x, optional<T> const& y )
861{ return !( y < x ) ; }
862
863template<class T>
864inline
865bool 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//
872namespace 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)
886template<class T>
887inline
888void 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
913template<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
Note: See TracBrowser for help on using the repository browser.