]> git.lyx.org Git - lyx.git/blob - 3rdparty/boost/boost/optional/detail/old_optional_implementation.hpp
Update to boost 1.72
[lyx.git] / 3rdparty / boost / boost / optional / detail / old_optional_implementation.hpp
1 // Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
2 // Copyright (C) 2014-2016 Andrzej Krzemienski.
3 //
4 // Use, modification, and distribution is subject to the Boost Software
5 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // See http://www.boost.org/libs/optional for documentation.
9 //
10 // You are welcome to contact the maintainer at:
11 //  akrzemi1@gmail.com
12
13 #ifndef BOOST_OPTIONAL_DETAIL_OLD_OPTIONAL_IMPLEMENTATION_AJK_28JAN2015_HPP
14 #define BOOST_OPTIONAL_DETAIL_OLD_OPTIONAL_IMPLEMENTATION_AJK_28JAN2015_HPP
15
16 #include <boost/detail/reference_content.hpp>
17 #include <boost/type_traits/is_reference.hpp>
18 #include <boost/type_traits/integral_constant.hpp>
19 #include <boost/type_traits/conditional.hpp>
20
21 namespace boost {
22
23 namespace optional_detail {
24
25
26 template<class T>
27 struct types_when_isnt_ref
28 {
29   typedef T const& reference_const_type ;
30   typedef T &      reference_type ;
31 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
32   typedef T &&     rval_reference_type ;
33   typedef T &&     reference_type_of_temporary_wrapper;
34 #ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
35   // GCC 4.4 has support for an early draft of rvalue references. The conforming version below
36   // causes warnings about returning references to a temporary.
37   static T&& move(T&& r) { return r; }
38 #else
39   static rval_reference_type move(reference_type r) { return boost::move(r); }
40 #endif
41 #endif
42   typedef T const* pointer_const_type ;
43   typedef T *      pointer_type ;
44   typedef T const& argument_type ;
45 } ;
46
47 template<class T>
48 struct types_when_is_ref
49 {
50   typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type raw_type ;
51
52   typedef raw_type&  reference_const_type ;
53   typedef raw_type&  reference_type ;
54 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
55   typedef BOOST_DEDUCED_TYPENAME remove_const<raw_type>::type&& rval_reference_type ;
56   typedef raw_type&  reference_type_of_temporary_wrapper;
57   static reference_type move(reference_type r) { return r; }
58 #endif
59   typedef raw_type*  pointer_const_type ;
60   typedef raw_type*  pointer_type ;
61   typedef raw_type&  argument_type ;
62 } ;
63
64 template <class To, class From>
65 void prevent_binding_rvalue_ref_to_optional_lvalue_ref()
66 {
67 #ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES
68   BOOST_STATIC_ASSERT_MSG(
69     !boost::is_lvalue_reference<To>::value || !boost::is_rvalue_reference<From>::value, 
70     "binding rvalue references to optional lvalue references is disallowed");
71 #endif    
72 }
73
74 struct optional_tag {} ;
75
76 template<class T>
77 class optional_base : public optional_tag
78 {
79   private :
80
81     typedef
82 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
83     BOOST_DEDUCED_TYPENAME
84 #endif
85     ::boost::detail::make_reference_content<T>::type internal_type ;
86
87     typedef aligned_storage<internal_type> storage_type ;
88
89     typedef types_when_isnt_ref<T> types_when_not_ref ;
90     typedef types_when_is_ref<T>   types_when_ref   ;
91
92     typedef optional_base<T> this_type ;
93
94   protected :
95
96     typedef T value_type ;
97
98     typedef true_type  is_reference_tag ;
99     typedef false_type is_not_reference_tag ;
100
101     typedef BOOST_DEDUCED_TYPENAME is_reference<T>::type is_reference_predicate ;
102
103   public:
104     typedef BOOST_DEDUCED_TYPENAME conditional<is_reference_predicate::value,types_when_ref,types_when_not_ref>::type types ;
105
106   protected:
107     typedef BOOST_DEDUCED_TYPENAME types::reference_type       reference_type ;
108     typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ;
109 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
110     typedef BOOST_DEDUCED_TYPENAME types::rval_reference_type  rval_reference_type ;
111     typedef BOOST_DEDUCED_TYPENAME types::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ;
112 #endif
113     typedef BOOST_DEDUCED_TYPENAME types::pointer_type         pointer_type ;
114     typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type   pointer_const_type ;
115     typedef BOOST_DEDUCED_TYPENAME types::argument_type        argument_type ;
116
117     // Creates an optional<T> uninitialized.
118     // No-throw
119     optional_base()
120       :
121       m_initialized(false) {}
122
123     // Creates an optional<T> uninitialized.
124     // No-throw
125     optional_base ( none_t )
126       :
127       m_initialized(false) {}
128
129     // Creates an optional<T> initialized with 'val'.
130     // Can throw if T::T(T const&) does
131     optional_base ( argument_type val )
132       :
133       m_initialized(false)
134     {
135         construct(val);
136     }
137
138 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
139     // move-construct an optional<T> initialized from an rvalue-ref to 'val'.
140     // Can throw if T::T(T&&) does
141     optional_base ( rval_reference_type val )
142       :
143       m_initialized(false)
144     {
145       construct( boost::move(val) );
146     }
147 #endif
148
149     // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional<T>.
150     // Can throw if T::T(T const&) does
151     optional_base ( bool cond, argument_type val )
152       :
153       m_initialized(false)
154     {
155       if ( cond )
156         construct(val);
157     }
158
159     // Creates a deep copy of another optional<T>
160     // Can throw if T::T(T const&) does
161     optional_base ( optional_base const& rhs )
162       :
163       m_initialized(false)
164     {
165       if ( rhs.is_initialized() )
166         construct(rhs.get_impl());
167     }
168
169 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
170     // Creates a deep move of another optional<T>
171     // Can throw if T::T(T&&) does
172     optional_base ( optional_base&& rhs )
173       :
174       m_initialized(false)
175     {
176       if ( rhs.is_initialized() )
177         construct( boost::move(rhs.get_impl()) );
178     }
179 #endif
180
181 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
182
183     template<class Expr, class PtrExpr>
184     explicit optional_base ( Expr&& expr, PtrExpr const* tag )
185       :
186       m_initialized(false)
187     {
188       construct(boost::forward<Expr>(expr),tag);
189     }
190
191 #else
192     // This is used for both converting and in-place constructions.
193     // Derived classes use the 'tag' to select the appropriate
194     // implementation (the correct 'construct()' overload)
195     template<class Expr>
196     explicit optional_base ( Expr const& expr, Expr const* tag )
197       :
198       m_initialized(false)
199     {
200       construct(expr,tag);
201     }
202
203 #endif
204
205
206     // No-throw (assuming T::~T() doesn't)
207     ~optional_base() { destroy() ; }
208
209     // Assigns from another optional<T> (deep-copies the rhs value)
210     void assign ( optional_base const& rhs )
211     {
212       if (is_initialized())
213       {
214         if ( rhs.is_initialized() )
215              assign_value(rhs.get_impl(), is_reference_predicate() );
216         else destroy();
217       }
218       else
219       {
220         if ( rhs.is_initialized() )
221           construct(rhs.get_impl());
222       }
223     }
224     
225 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
226     // Assigns from another optional<T> (deep-moves the rhs value)
227     void assign ( optional_base&& rhs )
228     {
229       if (is_initialized())
230       {
231         if ( rhs.is_initialized() )
232              assign_value(boost::move(rhs.get_impl()), is_reference_predicate() );
233         else destroy();
234       }
235       else
236       {
237         if ( rhs.is_initialized() )
238           construct(boost::move(rhs.get_impl()));
239       }
240     }
241 #endif 
242
243     // Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
244     template<class U>
245     void assign ( optional<U> const& rhs )
246     {
247       if (is_initialized())
248       {
249         if ( rhs.is_initialized() )
250 #ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
251           assign_value(rhs.get(), is_reference_predicate() );
252 #else
253           assign_value(static_cast<value_type>(rhs.get()), is_reference_predicate() );
254 #endif
255           
256         else destroy();
257       }
258       else
259       {
260         if ( rhs.is_initialized() )
261 #ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
262           construct(rhs.get());
263 #else
264           construct(static_cast<value_type>(rhs.get()));
265 #endif
266       }
267     }
268
269 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
270     // move-assigns from another _convertible_ optional<U> (deep-moves from the rhs value)
271     template<class U>
272     void assign ( optional<U>&& rhs )
273     {
274       typedef BOOST_DEDUCED_TYPENAME optional<U>::rval_reference_type ref_type;
275       if (is_initialized())
276       {
277         if ( rhs.is_initialized() )
278              assign_value(static_cast<ref_type>(rhs.get()), is_reference_predicate() );
279         else destroy();
280       }
281       else
282       {
283         if ( rhs.is_initialized() )
284           construct(static_cast<ref_type>(rhs.get()));
285       }
286     }
287 #endif
288     
289     // Assigns from a T (deep-copies the rhs value)
290     void assign ( argument_type val )
291     {
292       if (is_initialized())
293            assign_value(val, is_reference_predicate() );
294       else construct(val);
295     }
296     
297 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
298     // Assigns from a T (deep-moves the rhs value)
299     void assign ( rval_reference_type val )
300     {
301       if (is_initialized())
302            assign_value( boost::move(val), is_reference_predicate() );
303       else construct( boost::move(val) );
304     }
305 #endif
306
307     // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
308     // No-throw (assuming T::~T() doesn't)
309     void assign ( none_t ) BOOST_NOEXCEPT { destroy(); }
310
311 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
312
313 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
314     template<class Expr, class ExprPtr>
315     void assign_expr ( Expr&& expr, ExprPtr const* tag )
316     {
317       if (is_initialized())
318         assign_expr_to_initialized(boost::forward<Expr>(expr),tag);
319       else construct(boost::forward<Expr>(expr),tag);
320     }
321 #else
322     template<class Expr>
323     void assign_expr ( Expr const& expr, Expr const* tag )
324     {
325       if (is_initialized())
326         assign_expr_to_initialized(expr,tag);
327       else construct(expr,tag);
328     }
329 #endif
330
331 #endif
332
333   public :
334
335     // Destroys the current value, if any, leaving this UNINITIALIZED
336     // No-throw (assuming T::~T() doesn't)
337     void reset() BOOST_NOEXCEPT { destroy(); }
338
339     // **DEPPRECATED** Replaces the current value -if any- with 'val'
340     void reset ( argument_type val ) { assign(val); }
341
342     // Returns a pointer to the value if this is initialized, otherwise,
343     // returns NULL.
344     // No-throw
345     pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
346     pointer_type       get_ptr()       { return m_initialized ? get_ptr_impl() : 0 ; }
347
348     bool is_initialized() const { return m_initialized ; }
349
350   protected :
351
352     void construct ( argument_type val )
353      {
354        ::new (m_storage.address()) internal_type(val) ;
355        m_initialized = true ;
356      }
357      
358 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
359     void construct ( rval_reference_type val )
360      {
361        ::new (m_storage.address()) internal_type( types::move(val) ) ;
362        m_initialized = true ;
363      }
364 #endif
365
366
367 #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
368     // Constructs in-place
369     // upon exception *this is always uninitialized
370     template<class... Args>
371     void emplace_assign ( Args&&... args )
372      {
373        destroy();
374        ::new (m_storage.address()) internal_type( boost::forward<Args>(args)... );
375        m_initialized = true ;
376      }
377 #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
378     template<class Arg>
379     void emplace_assign ( Arg&& arg )
380      {
381        destroy();
382        ::new (m_storage.address()) internal_type( boost::forward<Arg>(arg) );
383        m_initialized = true ;
384      }
385      
386     void emplace_assign ()
387      {
388        destroy();
389        ::new (m_storage.address()) internal_type();
390        m_initialized = true ;
391      }
392 #else
393     template<class Arg>
394     void emplace_assign ( const Arg& arg )
395      {
396        destroy();
397        ::new (m_storage.address()) internal_type( arg );
398        m_initialized = true ;
399      }
400      
401     template<class Arg>
402     void emplace_assign ( Arg& arg )
403      {
404        destroy();
405        ::new (m_storage.address()) internal_type( arg );
406        m_initialized = true ;
407      }
408      
409     void emplace_assign ()
410      {
411        destroy();
412        ::new (m_storage.address()) internal_type();
413        m_initialized = true ;
414      }
415 #endif
416
417 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
418
419 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
420     // Constructs in-place using the given factory
421     template<class Expr>
422     void construct ( Expr&& factory, in_place_factory_base const* )
423      {
424        BOOST_STATIC_ASSERT ( !is_reference_predicate::value ) ;
425        boost_optional_detail::construct<value_type>(factory, m_storage.address());
426        m_initialized = true ;
427      }
428
429     // Constructs in-place using the given typed factory
430     template<class Expr>
431     void construct ( Expr&& factory, typed_in_place_factory_base const* )
432      {
433        BOOST_STATIC_ASSERT ( !is_reference_predicate::value ) ;
434        factory.apply(m_storage.address()) ;
435        m_initialized = true ;
436      }
437
438     template<class Expr>
439     void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag )
440      {
441        destroy();
442        construct(factory,tag);
443      }
444
445     // Constructs in-place using the given typed factory
446     template<class Expr>
447     void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag )
448      {
449        destroy();
450        construct(factory,tag);
451      }
452
453 #else
454     // Constructs in-place using the given factory
455     template<class Expr>
456     void construct ( Expr const& factory, in_place_factory_base const* )
457      {
458        BOOST_STATIC_ASSERT ( !is_reference_predicate::value ) ;
459        boost_optional_detail::construct<value_type>(factory, m_storage.address());
460        m_initialized = true ;
461      }
462
463     // Constructs in-place using the given typed factory
464     template<class Expr>
465     void construct ( Expr const& factory, typed_in_place_factory_base const* )
466      {
467        BOOST_STATIC_ASSERT ( !is_reference_predicate::value ) ;
468        factory.apply(m_storage.address()) ;
469        m_initialized = true ;
470      }
471
472     template<class Expr>
473     void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag )
474      {
475        destroy();
476        construct(factory,tag);
477      }
478
479     // Constructs in-place using the given typed factory
480     template<class Expr>
481     void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag )
482      {
483        destroy();
484        construct(factory,tag);
485      }
486 #endif
487
488 #endif
489
490 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
491     // Constructs using any expression implicitly convertible to the single argument
492     // of a one-argument T constructor.
493     // Converting constructions of optional<T> from optional<U> uses this function with
494     // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
495     template<class Expr>
496     void construct ( Expr&& expr, void const* )
497     {
498       new (m_storage.address()) internal_type(boost::forward<Expr>(expr)) ;
499       m_initialized = true ;
500     }
501
502     // Assigns using a form any expression implicitly convertible to the single argument
503     // of a T's assignment operator.
504     // Converting assignments of optional<T> from optional<U> uses this function with
505     // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
506     template<class Expr>
507     void assign_expr_to_initialized ( Expr&& expr, void const* )
508     {
509       assign_value(boost::forward<Expr>(expr), is_reference_predicate());
510     }
511 #else
512     // Constructs using any expression implicitly convertible to the single argument
513     // of a one-argument T constructor.
514     // Converting constructions of optional<T> from optional<U> uses this function with
515     // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
516     template<class Expr>
517     void construct ( Expr const& expr, void const* )
518      {
519        new (m_storage.address()) internal_type(expr) ;
520        m_initialized = true ;
521      }
522
523     // Assigns using a form any expression implicitly convertible to the single argument
524     // of a T's assignment operator.
525     // Converting assignments of optional<T> from optional<U> uses this function with
526     // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
527     template<class Expr>
528     void assign_expr_to_initialized ( Expr const& expr, void const* )
529      {
530        assign_value(expr, is_reference_predicate());
531      }
532
533 #endif
534
535 #ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
536     // BCB5.64 (and probably lower versions) workaround.
537     //   The in-place factories are supported by means of catch-all constructors
538     //   and assignment operators (the functions are parameterized in terms of
539     //   an arbitrary 'Expr' type)
540     //   This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U>
541     //   to the 'Expr'-taking functions even though explicit overloads are present for them.
542     //   Thus, the following overload is needed to properly handle the case when the 'lhs'
543     //   is another optional.
544     //
545     // For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error
546     // instead of choosing the wrong overload
547     //
548 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
549     // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
550     template<class Expr>
551     void construct ( Expr&& expr, optional_tag const* )
552      {
553        if ( expr.is_initialized() )
554        {
555          // An exception can be thrown here.
556          // It it happens, THIS will be left uninitialized.
557          new (m_storage.address()) internal_type(types::move(expr.get())) ;
558          m_initialized = true ;
559        }
560      }
561 #else
562     // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
563     template<class Expr>
564     void construct ( Expr const& expr, optional_tag const* )
565      {
566        if ( expr.is_initialized() )
567        {
568          // An exception can be thrown here.
569          // It it happens, THIS will be left uninitialized.
570          new (m_storage.address()) internal_type(expr.get()) ;
571          m_initialized = true ;
572        }
573      }
574 #endif
575 #endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
576
577     void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; }
578     void assign_value ( argument_type val, is_reference_tag     ) { construct(val); }
579 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
580     void assign_value ( rval_reference_type val, is_not_reference_tag ) { get_impl() = static_cast<rval_reference_type>(val); }
581     void assign_value ( rval_reference_type val, is_reference_tag     ) { construct( static_cast<rval_reference_type>(val) ); }
582 #endif
583
584     void destroy()
585     {
586       if ( m_initialized )
587         destroy_impl(is_reference_predicate()) ;
588     }
589
590     reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; }
591     reference_type       get_impl()       { return dereference(get_object(), is_reference_predicate() ) ; }
592
593     pointer_const_type get_ptr_impl() const { return cast_ptr(get_object(), is_reference_predicate() ) ; }
594     pointer_type       get_ptr_impl()       { return cast_ptr(get_object(), is_reference_predicate() ) ; }
595
596   private :
597
598     // internal_type can be either T or reference_content<T>
599 #if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
600     // This workaround is supposed to silence GCC warnings about broken strict aliasing rules
601     internal_type const* get_object() const
602     {
603         union { void const* ap_pvoid; internal_type const* as_ptype; } caster = { m_storage.address() };
604         return caster.as_ptype;
605     }
606     internal_type *      get_object()
607     {
608         union { void* ap_pvoid; internal_type* as_ptype; } caster = { m_storage.address() };
609         return caster.as_ptype;
610     }
611 #else
612     internal_type const* get_object() const { return static_cast<internal_type const*>(m_storage.address()); }
613     internal_type *      get_object()       { return static_cast<internal_type *>     (m_storage.address()); }
614 #endif
615
616     // reference_content<T> lacks an implicit conversion to T&, so the following is needed to obtain a proper reference.
617     reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; }
618     reference_type       dereference( internal_type*       p, is_not_reference_tag )       { return *p ; }
619     reference_const_type dereference( internal_type const* p, is_reference_tag     ) const { return p->get() ; }
620     reference_type       dereference( internal_type*       p, is_reference_tag     )       { return p->get() ; }
621
622 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
623     void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; }
624 #else
625     void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->~T() ; m_initialized = false ; }
626 #endif
627
628     void destroy_impl ( is_reference_tag     ) { m_initialized = false ; }
629
630     // If T is of reference type, trying to get a pointer to the held value must result in a compile-time error.
631     // Decent compilers should disallow conversions from reference_content<T>* to T*, but just in case,
632     // the following olverloads are used to filter out the case and guarantee an error in case of T being a reference.
633     pointer_const_type cast_ptr( internal_type const* p, is_not_reference_tag ) const { return p ; }
634     pointer_type       cast_ptr( internal_type *      p, is_not_reference_tag )       { return p ; }
635     pointer_const_type cast_ptr( internal_type const* p, is_reference_tag     ) const { return &p->get() ; }
636     pointer_type       cast_ptr( internal_type *      p, is_reference_tag     )       { return &p->get() ; }
637
638     bool m_initialized ;
639     storage_type m_storage ;
640 } ;
641
642 } // namespace optional_detail
643
644 template<class T>
645 class optional : public optional_detail::optional_base<T>
646 {
647     typedef optional_detail::optional_base<T> base ;
648
649   public :
650
651     typedef optional<T> this_type ;
652
653     typedef BOOST_DEDUCED_TYPENAME base::value_type           value_type ;
654     typedef BOOST_DEDUCED_TYPENAME base::reference_type       reference_type ;
655     typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
656 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
657     typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type  rval_reference_type ;
658     typedef BOOST_DEDUCED_TYPENAME base::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ;
659 #endif
660     typedef BOOST_DEDUCED_TYPENAME base::pointer_type         pointer_type ;
661     typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type   pointer_const_type ;
662     typedef BOOST_DEDUCED_TYPENAME base::argument_type        argument_type ;
663
664     // Creates an optional<T> uninitialized.
665     // No-throw
666     optional() BOOST_NOEXCEPT : base() {}
667
668     // Creates an optional<T> uninitialized.
669     // No-throw
670     optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {}
671
672     // Creates an optional<T> initialized with 'val'.
673     // Can throw if T::T(T const&) does
674     optional ( argument_type val ) : base(val) {}
675
676 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
677     // Creates an optional<T> initialized with 'move(val)'.
678     // Can throw if T::T(T &&) does
679     optional ( rval_reference_type val ) : base( boost::forward<T>(val) ) 
680       {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();}
681 #endif
682
683     // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
684     // Can throw if T::T(T const&) does
685     optional ( bool cond, argument_type val ) : base(cond,val) {}
686
687     // NOTE: MSVC needs templated versions first
688
689     // Creates a deep copy of another convertible optional<U>
690     // Requires a valid conversion from U to T.
691     // Can throw if T::T(U const&) does
692     template<class U>
693     explicit optional ( optional<U> const& rhs )
694       :
695       base()
696     {
697       if ( rhs.is_initialized() )
698         this->construct(rhs.get());
699     }
700     
701 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
702     // Creates a deep move of another convertible optional<U>
703     // Requires a valid conversion from U to T.
704     // Can throw if T::T(U&&) does
705     template<class U>
706     explicit optional ( optional<U> && rhs )
707       :
708       base()
709     {
710       if ( rhs.is_initialized() )
711         this->construct( boost::move(rhs.get()) );
712     }
713 #endif
714
715 #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
716     // Creates an optional<T> with an expression which can be either
717     //  (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
718     //  (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
719     //  (c) Any expression implicitly convertible to the single type
720     //      of a one-argument T's constructor.
721     //  (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
722     //       even though explicit overloads are present for these.
723     // Depending on the above some T ctor is called.
724     // Can throw if the resolved T ctor throws.
725 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
726
727
728   template<class Expr>
729   explicit optional ( Expr&& expr, 
730                       BOOST_DEDUCED_TYPENAME boost::disable_if_c<
731                         (boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value) || 
732                         boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value, bool >::type = true 
733   ) 
734     : base(boost::forward<Expr>(expr),boost::addressof(expr)) 
735     {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, Expr&&>();}
736
737 #else
738     template<class Expr>
739     explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
740 #endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
741 #endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
742
743     // Creates a deep copy of another optional<T>
744     // Can throw if T::T(T const&) does
745     optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
746
747 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
748     // Creates a deep move of another optional<T>
749     // Can throw if T::T(T&&) does
750     optional ( optional && rhs )
751       BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
752       : base( boost::move(rhs) )
753     {}
754
755 #endif
756    // No-throw (assuming T::~T() doesn't)
757     ~optional() {}
758
759 #if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
760     // Assigns from an expression. See corresponding constructor.
761     // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
762 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
763
764     template<class Expr>
765     BOOST_DEDUCED_TYPENAME boost::disable_if_c<
766       boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value || 
767         boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value,
768       optional&
769     >::type 
770     operator= ( Expr&& expr )
771       {
772         optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, Expr&&>();
773         this->assign_expr(boost::forward<Expr>(expr),boost::addressof(expr));
774         return *this ;
775       }
776
777 #else
778     template<class Expr>
779     optional& operator= ( Expr const& expr )
780       {
781         this->assign_expr(expr,boost::addressof(expr));
782         return *this ;
783       }
784 #endif // !defined  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
785 #endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
786
787     // Copy-assigns from another convertible optional<U> (converts && deep-copies the rhs value)
788     // Requires a valid conversion from U to T.
789     // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
790     template<class U>
791     optional& operator= ( optional<U> const& rhs )
792       {
793         this->assign(rhs);
794         return *this ;
795       }
796       
797 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
798     // Move-assigns from another convertible optional<U> (converts && deep-moves the rhs value)
799     // Requires a valid conversion from U to T.
800     // Basic Guarantee: If T::T( U && ) throws, this is left UNINITIALIZED
801     template<class U>
802     optional& operator= ( optional<U> && rhs )
803       {
804         this->assign(boost::move(rhs));
805         return *this ;
806       }
807 #endif
808
809     // Assigns from another optional<T> (deep-copies the rhs value)
810     // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
811     //  (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
812     optional& operator= ( optional const& rhs )
813       {
814         this->assign( static_cast<base const&>(rhs) ) ;
815         return *this ;
816       }
817
818 #ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
819     // Assigns from another optional<T> (deep-moves the rhs value)
820     optional& operator= ( optional && rhs ) 
821       BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
822       {
823         this->assign( static_cast<base &&>(rhs) ) ;
824         return *this ;
825       }
826 #endif
827
828     // Assigns from a T (deep-copies the rhs value)
829     // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
830     optional& operator= ( argument_type val )
831       {
832         this->assign( val ) ;
833         return *this ;
834       }
835
836 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
837     // Assigns from a T (deep-moves the rhs value)
838     optional& operator= ( rval_reference_type val )
839       {
840         optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();
841         this->assign( boost::move(val) ) ;
842         return *this ;
843       }
844 #endif
845
846     // Assigns from a "none"
847     // Which destroys the current value, if any, leaving this UNINITIALIZED
848     // No-throw (assuming T::~T() doesn't)
849     optional& operator= ( none_t none_ ) BOOST_NOEXCEPT
850       {
851         this->assign( none_ ) ;
852         return *this ;
853       }
854       
855 #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
856     // Constructs in-place
857     // upon exception *this is always uninitialized
858     template<class... Args>
859     void emplace ( Args&&... args )
860      {
861        this->emplace_assign( boost::forward<Args>(args)... );
862      }
863 #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
864     template<class Arg>
865     void emplace ( Arg&& arg )
866      {
867        this->emplace_assign( boost::forward<Arg>(arg) );
868      }
869      
870     void emplace ()
871      {
872        this->emplace_assign();
873      }
874 #else
875     template<class Arg>
876     void emplace ( const Arg& arg )
877      {
878        this->emplace_assign( arg );
879      }
880      
881     template<class Arg>
882     void emplace ( Arg& arg )
883      {
884        this->emplace_assign( arg );
885      }
886      
887     void emplace ()
888      {
889        this->emplace_assign();
890      }
891 #endif
892
893     void swap( optional & arg )
894       BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
895       {
896         // allow for Koenig lookup
897         boost::swap(*this, arg);
898       }
899
900
901     // Returns a reference to the value if this is initialized, otherwise,
902     // the behaviour is UNDEFINED
903     // No-throw
904     reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
905     reference_type       get()       { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
906
907     // Returns a copy of the value if this is initialized, 'v' otherwise
908     reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
909     reference_type       get_value_or ( reference_type       v )       { return this->is_initialized() ? get() : v ; }
910
911     // Returns a pointer to the value if this is initialized, otherwise,
912     // the behaviour is UNDEFINED
913     // No-throw
914     pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
915     pointer_type       operator->()       { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
916
917     // Returns a reference to the value if this is initialized, otherwise,
918     // the behaviour is UNDEFINED
919     // No-throw
920 #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) 
921     reference_const_type operator *() const& { return this->get() ; }
922     reference_type       operator *() &      { return this->get() ; }
923     reference_type_of_temporary_wrapper operator *() && { return base::types::move(this->get()) ; }
924 #else
925     reference_const_type operator *() const { return this->get() ; }
926     reference_type       operator *()       { return this->get() ; }
927 #endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS
928
929 #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) 
930     reference_const_type value() const&
931       { 
932         if (this->is_initialized())
933           return this->get() ;
934         else
935           throw_exception(bad_optional_access());
936       }
937       
938     reference_type value() &
939       { 
940         if (this->is_initialized())
941           return this->get() ;
942         else
943           throw_exception(bad_optional_access());
944       }
945       
946     reference_type_of_temporary_wrapper value() &&
947       { 
948         if (this->is_initialized())
949           return base::types::move(this->get()) ;
950         else
951           throw_exception(bad_optional_access());
952       }
953
954 #else 
955     reference_const_type value() const
956       { 
957         if (this->is_initialized())
958           return this->get() ;
959         else
960           throw_exception(bad_optional_access());
961       }
962       
963     reference_type value()
964       { 
965         if (this->is_initialized())
966           return this->get() ;
967         else
968           throw_exception(bad_optional_access());
969       }
970 #endif
971
972
973 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
974     template <class U>
975     value_type value_or ( U&& v ) const&
976       { 
977         if (this->is_initialized())
978           return get();
979         else
980           return boost::forward<U>(v);
981       }
982     
983     template <class U>
984     value_type value_or ( U&& v ) && 
985       { 
986         if (this->is_initialized())
987           return base::types::move(get());
988         else
989           return boost::forward<U>(v);
990       }
991 #elif !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
992     template <class U>
993     value_type value_or ( U&& v ) const 
994       {
995         if (this->is_initialized())
996           return get();
997         else
998           return boost::forward<U>(v);
999       }
1000 #else
1001     template <class U>
1002     value_type value_or ( U const& v ) const 
1003       { 
1004         if (this->is_initialized())
1005           return get();
1006         else
1007           return v;
1008       }
1009       
1010     template <class U>
1011     value_type value_or ( U& v ) const 
1012       { 
1013         if (this->is_initialized())
1014           return get();
1015         else
1016           return v;
1017       }
1018 #endif
1019
1020
1021 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
1022     template <typename F>
1023     value_type value_or_eval ( F f ) const&
1024       {
1025         if (this->is_initialized())
1026           return get();
1027         else
1028           return f();
1029       }
1030       
1031     template <typename F>
1032     value_type value_or_eval ( F f ) &&
1033       {
1034         if (this->is_initialized())
1035           return base::types::move(get());
1036         else
1037           return f();
1038       }
1039 #else
1040     template <typename F>
1041     value_type value_or_eval ( F f ) const
1042       {
1043         if (this->is_initialized())
1044           return get();
1045         else
1046           return f();
1047       }
1048 #endif
1049       
1050     bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; }
1051     
1052     BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
1053 } ;
1054
1055 } // namespace boost
1056
1057
1058 #endif // header guard