]> git.lyx.org Git - lyx.git/blob - boost/boost/optional/optional.hpp
Upgrade to boost 1.33.1
[lyx.git] / boost / boost / optional / optional.hpp
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_t.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__, <= 0x564)
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
80 namespace boost {
81
82 class in_place_factory_base ;
83 class typed_in_place_factory_base ;
84
85 namespace optional_detail {
86
87 // This local class is used instead of that in "aligned_storage.hpp"
88 // because I've found the 'official' class to ICE BCB5.5
89 // when some types are used with optional<>
90 // (due to sizeof() passed down as a non-type template parameter)
91 template <class T>
92 class aligned_storage
93 {
94     // Borland ICEs if unnamed unions are used for this!
95     union dummy_u
96     {
97         char data[ sizeof(T) ];
98         BOOST_DEDUCED_TYPENAME type_with_alignment<
99           ::boost::alignment_of<T>::value >::type aligner_;
100     } dummy_ ;
101
102   public:
103
104     void const* address() const { return &dummy_.data[0]; }
105     void      * address()       { return &dummy_.data[0]; }
106 } ;
107
108 template<class T>
109 struct types_when_isnt_ref
110 {
111   typedef T const& reference_const_type ;
112   typedef T &      reference_type ;
113   typedef T const* pointer_const_type ;
114   typedef T *      pointer_type ;
115   typedef T const& argument_type ;
116 } ;
117 template<class T>
118 struct types_when_is_ref
119 {
120   typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type raw_type ;
121
122   typedef raw_type& reference_const_type ;
123   typedef raw_type& reference_type ;
124   typedef raw_type* pointer_const_type ;
125   typedef raw_type* pointer_type ;
126   typedef raw_type& argument_type ;
127 } ;
128
129 struct optional_tag {} ;
130
131 template<class T>
132 class optional_base : public optional_tag
133 {
134   private :
135
136     typedef BOOST_DEDUCED_TYPENAME detail::make_reference_content<T>::type internal_type ;
137
138     typedef aligned_storage<internal_type> storage_type ;
139
140     typedef types_when_isnt_ref<T> types_when_not_ref ;
141     typedef types_when_is_ref<T>   types_when_ref   ;
142
143     typedef optional_base<T> this_type ;
144
145   protected :
146
147     typedef T value_type ;
148
149     typedef mpl::true_  is_reference_tag ;
150     typedef mpl::false_ is_not_reference_tag ;
151
152     typedef BOOST_DEDUCED_TYPENAME is_reference<T>::type is_reference_predicate ;
153
154     typedef BOOST_DEDUCED_TYPENAME mpl::if_<is_reference_predicate,types_when_ref,types_when_not_ref>::type types ;
155
156     typedef bool (this_type::*unspecified_bool_type)() const;
157
158     typedef BOOST_DEDUCED_TYPENAME types::reference_type       reference_type ;
159     typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ;
160     typedef BOOST_DEDUCED_TYPENAME types::pointer_type         pointer_type ;
161     typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type   pointer_const_type ;
162     typedef BOOST_DEDUCED_TYPENAME types::argument_type        argument_type ;
163
164     // Creates an optional<T> uninitialized.
165     // No-throw
166     optional_base()
167       :
168       m_initialized(false) {}
169
170     // Creates an optional<T> uninitialized.
171     // No-throw
172     optional_base ( none_t const& )
173       :
174       m_initialized(false) {}
175
176     // Creates an optional<T> initialized with 'val'.
177     // Can throw if T::T(T const&) does
178     optional_base ( argument_type val )
179       :
180       m_initialized(false)
181     {
182       construct(val);
183     }
184
185     // Creates a deep copy of another optional<T>
186     // Can throw if T::T(T const&) does
187     optional_base ( optional_base const& rhs )
188       :
189       m_initialized(false)
190     {
191       if ( rhs.is_initialized() )
192         construct(rhs.get_impl());
193     }
194
195
196     // This is used for both converting and in-place constructions.
197     // Derived classes use the 'tag' to select the appropriate
198     // implementation (the correct 'construct()' overload)
199     template<class Expr>
200     explicit optional_base ( Expr const& expr, Expr const* tag )
201       :
202       m_initialized(false)
203     {
204       construct(expr,tag);
205     }
206
207
208
209     // No-throw (assuming T::~T() doesn't)
210     ~optional_base() { destroy() ; }
211
212     // Assigns from another optional<T> (deep-copies the rhs value)
213     void assign ( optional_base const& rhs )
214     {
215       if (is_initialized())
216       {
217         if ( rhs.is_initialized() )
218              assign_value(rhs.get_impl(), is_reference_predicate() );
219         else destroy();
220       }
221       else
222       {
223         if ( rhs.is_initialized() )
224           construct(rhs.get_impl());
225       }
226     }
227
228     // Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
229     template<class U>
230     void assign ( optional<U> const& rhs )
231     {
232       if (is_initialized())
233       {
234         if ( rhs.is_initialized() )
235              assign_value(static_cast<value_type>(rhs.get()), is_reference_predicate() );
236         else destroy();
237       }
238       else
239       {
240         if ( rhs.is_initialized() )
241           construct(static_cast<value_type>(rhs.get()));
242       }
243     }
244
245     // Assigns from a T (deep-copies the rhs value)
246     void assign ( argument_type val )
247     {
248       if (is_initialized())
249            assign_value(val, is_reference_predicate() );
250       else construct(val);
251     }
252
253     // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
254     // No-throw (assuming T::~T() doesn't)
255     void assign ( none_t const& ) { destroy(); }
256
257 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
258     template<class Expr>
259     void assign_expr ( Expr const& expr, Expr const* tag )
260       {
261         if (is_initialized())
262              assign_expr_to_initialized(expr,tag);
263         else construct(expr,tag);
264       }
265 #endif
266
267   public :
268
269     // Destroys the current value, if any, leaving this UNINITIALIZED
270     // No-throw (assuming T::~T() doesn't)
271     void reset() { destroy(); }
272
273     // Replaces the current value -if any- with 'val'
274     void reset ( argument_type val ) { assign(val); }
275
276     // Returns a pointer to the value if this is initialized, otherwise,
277     // returns NULL.
278     // No-throw
279     pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
280     pointer_type       get_ptr()       { return m_initialized ? get_ptr_impl() : 0 ; }
281
282     bool is_initialized() const { return m_initialized ; }
283
284   protected :
285
286     void construct ( argument_type val )
287      {
288        new (m_storage.address()) internal_type(val) ;
289        m_initialized = true ;
290      }
291
292 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
293     // Constructs in-place using the given factory
294     template<class Expr>
295     void construct ( Expr const& factory, in_place_factory_base const* )
296      {
297        BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
298        factory.BOOST_NESTED_TEMPLATE apply<value_type>(m_storage.address()) ;
299        m_initialized = true ;
300      }
301
302     // Constructs in-place using the given typed factory
303     template<class Expr>
304     void construct ( Expr const& factory, typed_in_place_factory_base const* )
305      {
306        BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
307        factory.apply(m_storage.address()) ;
308        m_initialized = true ;
309      }
310
311     template<class Expr>
312     void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag )
313      {
314        destroy();
315        construct(factory,tag);
316      }
317
318     // Constructs in-place using the given typed factory
319     template<class Expr>
320     void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag )
321      {
322        destroy();
323        construct(factory,tag);
324      }
325 #endif
326
327     // Constructs using any expression implicitely convertible to the single argument
328     // of a one-argument T constructor.
329     // Converting constructions of optional<T> from optional<U> uses this function with
330     // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
331     template<class Expr>
332     void construct ( Expr const& expr, void const* )
333      {
334        new (m_storage.address()) internal_type(expr) ;
335        m_initialized = true ;
336      }
337
338     // Assigns using a form any expression implicitely convertible to the single argument
339     // of a T's assignment operator.
340     // Converting assignments of optional<T> from optional<U> uses this function with
341     // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
342     template<class Expr>
343     void assign_expr_to_initialized ( Expr const& expr, void const* )
344      {
345        assign_value(expr, is_reference_predicate());
346      }
347
348 #ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
349     // BCB5.64 (and probably lower versions) workaround.
350     //   The in-place factories are supported by means of catch-all constructors
351     //   and assignment operators (the functions are parameterized in terms of
352     //   an arbitrary 'Expr' type)
353     //   This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U>
354     //   to the 'Expr'-taking functions even though explicit overloads are present for them.
355     //   Thus, the following overload is needed to properly handle the case when the 'lhs'
356     //   is another optional.
357     //
358     // For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error
359     // instead of choosing the wrong overload
360     //
361     // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
362     template<class Expr>
363     void construct ( Expr const& expr, optional_tag const* )
364      {
365        if ( expr.is_initialized() )
366        {
367          // An exception can be thrown here.
368          // It it happens, THIS will be left uninitialized.
369          new (m_storage.address()) internal_type(expr.get()) ;
370          m_initialized = true ;
371        }
372      }
373 #endif
374
375     void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; }
376     void assign_value ( argument_type val, is_reference_tag     ) { construct(val); }
377
378     void destroy()
379     {
380       if ( m_initialized )
381         destroy_impl(is_reference_predicate()) ;
382     }
383
384     unspecified_bool_type safe_bool() const { return m_initialized ? &this_type::is_initialized : 0 ; }
385
386     reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; }
387     reference_type       get_impl()       { return dereference(get_object(), is_reference_predicate() ) ; }
388
389     pointer_const_type get_ptr_impl() const { return cast_ptr(get_object(), is_reference_predicate() ) ; }
390     pointer_type       get_ptr_impl()       { return cast_ptr(get_object(), is_reference_predicate() ) ; }
391
392   private :
393
394     // internal_type can be either T or reference_content<T>
395     internal_type const* get_object() const { return static_cast<internal_type const*>(m_storage.address()); }
396     internal_type *      get_object()       { return static_cast<internal_type *>     (m_storage.address()); }
397
398     // reference_content<T> lacks an implicit conversion to T&, so the following is needed to obtain a proper reference.
399     reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; }
400     reference_type       dereference( internal_type*       p, is_not_reference_tag )       { return *p ; }
401     reference_const_type dereference( internal_type const* p, is_reference_tag     ) const { return p->get() ; }
402     reference_type       dereference( internal_type*       p, is_reference_tag     )       { return p->get() ; }
403
404 #if BOOST_WORKAROUND(__BORLANDC__, <= 0x564)
405     void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; }
406 #else
407     void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->T::~T() ; m_initialized = false ; }
408 #endif
409
410     void destroy_impl ( is_reference_tag     ) { m_initialized = false ; }
411
412     // If T is of reference type, trying to get a pointer to the held value must result in a compile-time error.
413     // Decent compilers should disallow conversions from reference_content<T>* to T*, but just in case,
414     // the following olverloads are used to filter out the case and guarantee an error in case of T being a reference.
415     pointer_const_type cast_ptr( internal_type const* p, is_not_reference_tag ) const { return p ; }
416     pointer_type       cast_ptr( internal_type *      p, is_not_reference_tag )       { return p ; }
417
418     bool m_initialized ;
419     storage_type m_storage ;
420 } ;
421
422 } // namespace optional_detail
423
424 template<class T>
425 class optional : public optional_detail::optional_base<T>
426 {
427     typedef optional_detail::optional_base<T> base ;
428
429     typedef BOOST_DEDUCED_TYPENAME base::unspecified_bool_type  unspecified_bool_type ;
430
431   public :
432
433     typedef optional<T> this_type ;
434
435     typedef BOOST_DEDUCED_TYPENAME base::value_type           value_type ;
436     typedef BOOST_DEDUCED_TYPENAME base::reference_type       reference_type ;
437     typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
438     typedef BOOST_DEDUCED_TYPENAME base::pointer_type         pointer_type ;
439     typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type   pointer_const_type ;
440     typedef BOOST_DEDUCED_TYPENAME base::argument_type        argument_type ;
441
442     // Creates an optional<T> uninitialized.
443     // No-throw
444     optional() : base() {}
445
446     // Creates an optional<T> uninitialized.
447     // No-throw
448     optional( none_t const& none_ ) : base(none_) {}
449
450     // Creates an optional<T> initialized with 'val'.
451     // Can throw if T::T(T const&) does
452     optional ( argument_type val ) : base(val) {}
453
454
455 #ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
456     // NOTE: MSVC needs templated versions first
457
458     // Creates a deep copy of another convertible optional<U>
459     // Requires a valid conversion from U to T.
460     // Can throw if T::T(U const&) does
461     template<class U>
462     explicit optional ( optional<U> const& rhs )
463       :
464       base()
465     {
466       if ( rhs.is_initialized() )
467         this->construct(rhs.get());
468     }
469 #endif
470
471 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
472     // Creates an optional<T> with an expression which can be either
473     //  (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
474     //  (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
475     //  (c) Any expression implicitely convertible to the single type
476     //      of a one-argument T's constructor.
477     //  (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
478     //       even though explicit overloads are present for these.
479     // Depending on the above some T ctor is called.
480     // Can throw is the resolved T ctor throws.
481     template<class Expr>
482     explicit optional ( Expr const& expr ) : base(expr,&expr) {}
483 #endif
484
485     // Creates a deep copy of another optional<T>
486     // Can throw if T::T(T const&) does
487     optional ( optional const& rhs ) : base(rhs) {}
488
489    // No-throw (assuming T::~T() doesn't)
490     ~optional() {}
491
492 #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
493     // Assigns from an expression. See corresponding constructor.
494     // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
495     template<class Expr>
496     optional& operator= ( Expr expr )
497       {
498         this->assign_expr(expr,&expr);
499         return *this ;
500       }
501 #endif
502
503
504 #ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
505     // Assigns from another convertible optional<U> (converts && deep-copies the rhs value)
506     // Requires a valid conversion from U to T.
507     // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
508     template<class U>
509     optional& operator= ( optional<U> const& rhs )
510       {
511         this->assign(rhs);
512         return *this ;
513       }
514 #endif
515
516     // Assigns from another optional<T> (deep-copies the rhs value)
517     // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
518     //  (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
519     optional& operator= ( optional const& rhs )
520       {
521         this->assign( rhs ) ;
522         return *this ;
523       }
524
525     // Assigns from a T (deep-copies the rhs value)
526     // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
527     optional& operator= ( argument_type val )
528       {
529         this->assign( val ) ;
530         return *this ;
531       }
532
533     // Assigns from a "none"
534     // Which destroys the current value, if any, leaving this UNINITIALIZED
535     // No-throw (assuming T::~T() doesn't)
536     optional& operator= ( none_t const& none_ )
537       {
538         this->assign( none_ ) ;
539         return *this ;
540       }
541
542     // Returns a reference to the value if this is initialized, otherwise,
543     // the behaviour is UNDEFINED
544     // No-throw
545     reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
546     reference_type       get()       { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
547
548     // Returns a pointer to the value if this is initialized, otherwise,
549     // the behaviour is UNDEFINED
550     // No-throw
551     pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
552     pointer_type       operator->()       { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
553
554     // Returns a reference to the value if this is initialized, otherwise,
555     // the behaviour is UNDEFINED
556     // No-throw
557     reference_const_type operator *() const { return this->get() ; }
558     reference_type       operator *()       { return this->get() ; }
559
560     // implicit conversion to "bool"
561     // No-throw
562     operator unspecified_bool_type() const { return this->safe_bool() ; }
563
564        // This is provided for those compilers which don't like the conversion to bool
565        // on some contexts.
566        bool operator!() const { return !this->is_initialized() ; }
567 } ;
568
569 // Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
570 // No-throw
571 template<class T>
572 inline
573 BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
574 get ( optional<T> const& opt )
575 {
576   return opt.get() ;
577 }
578
579 template<class T>
580 inline
581 BOOST_DEDUCED_TYPENAME optional<T>::reference_type
582 get ( optional<T>& opt )
583 {
584   return opt.get() ;
585 }
586
587 // Returns a pointer to the value if this is initialized, otherwise, returns NULL.
588 // No-throw
589 template<class T>
590 inline
591 BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
592 get ( optional<T> const* opt )
593 {
594   return opt->get_ptr() ;
595 }
596
597 template<class T>
598 inline
599 BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
600 get ( optional<T>* opt )
601 {
602   return opt->get_ptr() ;
603 }
604
605 // Returns a pointer to the value if this is initialized, otherwise, returns NULL.
606 // No-throw
607 template<class T>
608 inline
609 BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
610 get_pointer ( optional<T> const& opt )
611 {
612   return opt.get_ptr() ;
613 }
614
615 template<class T>
616 inline
617 BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
618 get_pointer ( optional<T>& opt )
619 {
620   return opt.get_ptr() ;
621 }
622
623 // optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values).
624 // WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead.
625
626 template<class T>
627 inline
628 bool operator == ( optional<T> const& x, optional<T> const& y )
629 { return equal_pointees(x,y); }
630
631 template<class T>
632 inline
633 bool operator < ( optional<T> const& x, optional<T> const& y )
634 { return less_pointees(x,y); }
635
636 template<class T>
637 inline
638 bool operator != ( optional<T> const& x, optional<T> const& y )
639 { return !( x == y ) ; }
640
641 template<class T>
642 inline
643 bool operator > ( optional<T> const& x, optional<T> const& y )
644 { return y < x ; }
645
646 template<class T>
647 inline
648 bool operator <= ( optional<T> const& x, optional<T> const& y )
649 { return !( y < x ) ; }
650
651 template<class T>
652 inline
653 bool operator >= ( optional<T> const& x, optional<T> const& y )
654 { return !( x < y ) ; }
655
656 template<class T>
657 inline
658 bool operator == ( optional<T> const& x, none_t const& )
659 { return equal_pointees(x, optional<T>() ); }
660
661 template<class T>
662 inline
663 bool operator < ( optional<T> const& x, none_t const& )
664 { return less_pointees(x,optional<T>() ); }
665
666 template<class T>
667 inline
668 bool operator != ( optional<T> const& x, none_t const& y )
669 { return !( x == y ) ; }
670
671 template<class T>
672 inline
673 bool operator > ( optional<T> const& x, none_t const& y )
674 { return y < x ; }
675
676 template<class T>
677 inline
678 bool operator <= ( optional<T> const& x, none_t const& y )
679 { return !( y < x ) ; }
680
681 template<class T>
682 inline
683 bool operator >= ( optional<T> const& x, none_t const& y )
684 { return !( x < y ) ; }
685
686 template<class T>
687 inline
688 bool operator == ( none_t const& x, optional<T> const& y )
689 { return equal_pointees(optional<T>() ,y); }
690
691 template<class T>
692 inline
693 bool operator < ( none_t const& x, optional<T> const& y )
694 { return less_pointees(optional<T>() ,y); }
695
696 template<class T>
697 inline
698 bool operator != ( none_t const& x, optional<T> const& y )
699 { return !( x == y ) ; }
700
701 template<class T>
702 inline
703 bool operator > ( none_t const& x, optional<T> const& y )
704 { return y < x ; }
705
706 template<class T>
707 inline
708 bool operator <= ( none_t const& x, optional<T> const& y )
709 { return !( y < x ) ; }
710
711 template<class T>
712 inline
713 bool operator >= ( none_t const& x, optional<T> const& y )
714 { return !( x < y ) ; }
715
716 //
717 // The following swap implementation follows the GCC workaround as found in
718 //  "boost/detail/compressed_pair.hpp"
719 //
720 namespace optional_detail {
721
722 // GCC < 3.2 gets the using declaration at namespace scope (FLC, DWA)
723 #if BOOST_WORKAROUND(__GNUC__, < 3)                             \
724     || BOOST_WORKAROUND(__GNUC__, == 3) && __GNUC_MINOR__ <= 2
725    using std::swap;
726 #define BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE
727 #endif
728
729 // optional's swap:
730 // If both are initialized, calls swap(T&, T&). If this swap throws, both will remain initialized but their values are now unspecified.
731 // If only one is initialized, calls U.reset(*I), THEN I.reset().
732 // If U.reset(*I) throws, both are left UNCHANGED (U is kept uinitialized and I is never reset)
733 // If both are uninitialized, do nothing (no-throw)
734 template<class T>
735 inline
736 void optional_swap ( optional<T>& x, optional<T>& y )
737 {
738   if ( !x && !!y )
739   {
740     x.reset(*y);
741     y.reset();
742   }
743   else if ( !!x && !y )
744   {
745     y.reset(*x);
746     x.reset();
747   }
748   else if ( !!x && !!y )
749   {
750 // GCC > 3.2 and all other compilers have the using declaration at function scope (FLC)
751 #ifndef BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE
752     // allow for Koenig lookup
753     using std::swap ;
754 #endif
755     swap(*x,*y);
756   }
757 }
758
759 } // namespace optional_detail
760
761 template<class T> inline void swap ( optional<T>& x, optional<T>& y )
762 {
763   optional_detail::optional_swap(x,y);
764 }
765
766 template<class T> inline optional<T> make_optional ( T const& v )
767 {
768   return optional<T>(v);
769 }
770
771 } // namespace boost
772
773 #endif
774