1// trivilally-copyable version of the storage
2
3template<class T>
4class tc_optional_base : public optional_tag
5{
6 private :
7
8 typedef tc_optional_base<T> this_type ;
9
10 protected :
11
12 typedef T value_type ;
13
14 protected:
15 typedef T & reference_type ;
16 typedef T const& reference_const_type ;
17#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
18 typedef T && rval_reference_type ;
19 typedef T && reference_type_of_temporary_wrapper ;
20#endif
21 typedef T * pointer_type ;
22 typedef T const* pointer_const_type ;
23 typedef T const& argument_type ;
24
25 tc_optional_base()
26 :
27 m_initialized(false) {}
28
29 tc_optional_base ( none_t )
30 :
31 m_initialized(false) {}
32
33 tc_optional_base ( argument_type val )
34 :
35 m_initialized(true), m_storage(val) {}
36
37 tc_optional_base ( bool cond, argument_type val )
38 :
39 m_initialized(cond), m_storage(val) {}
40
41 // tc_optional_base ( tc_optional_base const& ) = default;
42
43
44#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
45
46 template<class Expr, class PtrExpr>
47 explicit tc_optional_base ( Expr&& expr, PtrExpr const* tag )
48 :
49 m_initialized(false)
50 {
51 construct(boost::forward<Expr>(expr),tag);
52 }
53
54#else
55 // This is used for both converting and in-place constructions.
56 // Derived classes use the 'tag' to select the appropriate
57 // implementation (the correct 'construct()' overload)
58 template<class Expr>
59 explicit tc_optional_base ( Expr const& expr, Expr const* tag )
60 :
61 m_initialized(false)
62 {
63 construct(expr,tag);
64 }
65
66#endif
67
68 // tc_optional_base& operator= ( tc_optional_base const& ) = default;
69 // ~tc_optional_base() = default;
70
71 // Assigns from another optional<T> (deep-copies the rhs value)
72 void assign ( tc_optional_base const& rhs )
73 {
74 this->operator=(rhs);
75 }
76
77 // Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
78 template<class U>
79 void assign ( optional<U> const& rhs )
80 {
81 if ( rhs.is_initialized() )
82#ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
83 m_storage = rhs.get();
84#else
85 m_storage = static_cast<value_type>(rhs.get());
86#endif
87
88 m_initialized = rhs.is_initialized();
89 }
90
91#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
92 // move-assigns from another _convertible_ optional<U> (deep-moves from the rhs value)
93 template<class U>
94 void assign ( optional<U>&& rhs )
95 {
96 typedef BOOST_DEDUCED_TYPENAME optional<U>::rval_reference_type ref_type;
97 if ( rhs.is_initialized() )
98 m_storage = static_cast<ref_type>(rhs.get());
99 m_initialized = rhs.is_initialized();
100 }
101#endif
102
103 void assign ( argument_type val )
104 {
105 construct(val);
106 }
107
108 void assign ( none_t ) { destroy(); }
109
110#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
111
112#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
113 template<class Expr, class ExprPtr>
114 void assign_expr ( Expr&& expr, ExprPtr const* tag )
115 {
116 construct(boost::forward<Expr>(expr),tag);
117 }
118#else
119 template<class Expr>
120 void assign_expr ( Expr const& expr, Expr const* tag )
121 {
122 construct(expr,tag);
123 }
124#endif
125
126#endif
127
128 public :
129
130 // **DEPPRECATED** Destroys the current value, if any, leaving this UNINITIALIZED
131 // No-throw (assuming T::~T() doesn't)
132 void reset() BOOST_NOEXCEPT { destroy(); }
133
134 // **DEPPRECATED** Replaces the current value -if any- with 'val'
135 void reset ( argument_type val ) BOOST_NOEXCEPT { assign(val); }
136
137 // Returns a pointer to the value if this is initialized, otherwise,
138 // returns NULL.
139 // No-throw
140 pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
141 pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; }
142
143 bool is_initialized() const { return m_initialized ; }
144
145 protected :
146
147 void construct ( argument_type val )
148 {
149 m_storage = val ;
150 m_initialized = true ;
151 }
152
153
154#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
155 // Constructs in-place
156 // upon exception *this is always uninitialized
157 template<class... Args>
158 void construct ( in_place_init_t, Args&&... args )
159 {
160 m_storage = value_type( boost::forward<Args>(args)... ) ;
161 m_initialized = true ;
162 }
163
164 template<class... Args>
165 void emplace_assign ( Args&&... args )
166 {
167 construct(in_place_init, boost::forward<Args>(args)...);
168 }
169
170 template<class... Args>
171 explicit tc_optional_base ( in_place_init_t, Args&&... args )
172 :
173 m_initialized(false)
174 {
175 construct(in_place_init, boost::forward<Args>(args)...);
176 }
177
178 template<class... Args>
179 explicit tc_optional_base ( in_place_init_if_t, bool cond, Args&&... args )
180 :
181 m_initialized(false)
182 {
183 if ( cond )
184 construct(in_place_init, boost::forward<Args>(args)...);
185 }
186#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
187 template<class Arg>
188 void construct ( in_place_init_t, Arg&& arg )
189 {
190 m_storage = value_type( boost::forward<Arg>(arg) );
191 m_initialized = true ;
192 }
193
194 void construct ( in_place_init_t )
195 {
196 m_storage = value_type();
197 m_initialized = true ;
198 }
199
200 template<class Arg>
201 void emplace_assign ( Arg&& arg )
202 {
203 construct(in_place_init, boost::forward<Arg>(arg)) ;
204 }
205
206 void emplace_assign ()
207 {
208 construct(in_place_init) ;
209 }
210
211 template<class Arg>
212 explicit tc_optional_base ( in_place_init_t, Arg&& arg )
213 :
214 m_initialized(false)
215 {
216 construct(in_place_init, boost::forward<Arg>(arg));
217 }
218
219 explicit tc_optional_base ( in_place_init_t )
220 :
221 m_initialized(false), m_storage() {}
222
223 template<class Arg>
224 explicit tc_optional_base ( in_place_init_if_t, bool cond, Arg&& arg )
225 :
226 m_initialized(false)
227 {
228 if ( cond )
229 construct(in_place_init, boost::forward<Arg>(arg));
230 }
231
232 explicit tc_optional_base ( in_place_init_if_t, bool cond )
233 :
234 m_initialized(false)
235 {
236 if ( cond )
237 construct(in_place_init);
238 }
239
240#else
241
242 template<class Arg>
243 void construct ( in_place_init_t, const Arg& arg )
244 {
245 m_storage = value_type( arg );
246 m_initialized = true ;
247 }
248
249 template<class Arg>
250 void construct ( in_place_init_t, Arg& arg )
251 {
252 m_storage = value_type( arg );
253 m_initialized = true ;
254 }
255
256 void construct ( in_place_init_t )
257 {
258 m_storage = value_type();
259 m_initialized = true ;
260 }
261
262 template<class Arg>
263 void emplace_assign ( const Arg& arg )
264 {
265 construct(in_place_init, arg);
266 }
267
268 template<class Arg>
269 void emplace_assign ( Arg& arg )
270 {
271 construct(in_place_init, arg);
272 }
273
274 void emplace_assign ()
275 {
276 construct(in_place_init);
277 }
278
279 template<class Arg>
280 explicit tc_optional_base ( in_place_init_t, const Arg& arg )
281 : m_initialized(false)
282 {
283 construct(in_place_init, arg);
284 }
285
286 template<class Arg>
287 explicit tc_optional_base ( in_place_init_t, Arg& arg )
288 : m_initialized(false)
289 {
290 construct(in_place_init, arg);
291 }
292
293 explicit tc_optional_base ( in_place_init_t )
294 : m_initialized(false)
295 {
296 construct(in_place_init);
297 }
298
299 template<class Arg>
300 explicit tc_optional_base ( in_place_init_if_t, bool cond, const Arg& arg )
301 : m_initialized(false)
302 {
303 if ( cond )
304 construct(in_place_init, arg);
305 }
306
307 template<class Arg>
308 explicit tc_optional_base ( in_place_init_if_t, bool cond, Arg& arg )
309 : m_initialized(false)
310 {
311 if ( cond )
312 construct(in_place_init, arg);
313 }
314
315 explicit tc_optional_base ( in_place_init_if_t, bool cond )
316 : m_initialized(false)
317 {
318 if ( cond )
319 construct(in_place_init);
320 }
321#endif
322
323#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
324
325#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
326 // Constructs in-place using the given factory
327 template<class Expr>
328 void construct ( Expr&& factory, in_place_factory_base const* )
329 {
330 boost_optional_detail::construct<value_type>(factory, boost::addressof(m_storage));
331 m_initialized = true ;
332 }
333
334 // Constructs in-place using the given typed factory
335 template<class Expr>
336 void construct ( Expr&& factory, typed_in_place_factory_base const* )
337 {
338 factory.apply(boost::addressof(m_storage)) ;
339 m_initialized = true ;
340 }
341
342 template<class Expr>
343 void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag )
344 {
345 destroy();
346 construct(factory,tag);
347 }
348
349 // Constructs in-place using the given typed factory
350 template<class Expr>
351 void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag )
352 {
353 destroy();
354 construct(factory,tag);
355 }
356
357#else
358 // Constructs in-place using the given factory
359 template<class Expr>
360 void construct ( Expr const& factory, in_place_factory_base const* )
361 {
362 boost_optional_detail::construct<value_type>(factory, m_storage.address());
363 m_initialized = true ;
364 }
365
366 // Constructs in-place using the given typed factory
367 template<class Expr>
368 void construct ( Expr const& factory, typed_in_place_factory_base const* )
369 {
370 factory.apply(boost::addressof(m_storage)) ;
371 m_initialized = true ;
372 }
373
374 template<class Expr>
375 void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag )
376 {
377 destroy();
378 construct(factory,tag);
379 }
380
381 // Constructs in-place using the given typed factory
382 template<class Expr>
383 void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag )
384 {
385 destroy();
386 construct(factory,tag);
387 }
388#endif
389
390#endif
391
392#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
393 // Constructs using any expression implicitly convertible to the single argument
394 // of a one-argument T constructor.
395 // Converting constructions of optional<T> from optional<U> uses this function with
396 // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
397 template<class Expr>
398 void construct ( Expr&& expr, void const* )
399 {
400 m_storage = value_type(boost::forward<Expr>(expr)) ;
401 m_initialized = true ;
402 }
403
404 // Assigns using a form any expression implicitly convertible to the single argument
405 // of a T's assignment operator.
406 // Converting assignments of optional<T> from optional<U> uses this function with
407 // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
408 template<class Expr>
409 void assign_expr_to_initialized ( Expr&& expr, void const* )
410 {
411 assign_value( boost::forward<Expr>(expr) );
412 }
413#else
414 // Constructs using any expression implicitly convertible to the single argument
415 // of a one-argument T constructor.
416 // Converting constructions of optional<T> from optional<U> uses this function with
417 // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
418 template<class Expr>
419 void construct ( Expr const& expr, void const* )
420 {
421 m_storage = value_type(expr) ;
422 m_initialized = true ;
423 }
424
425 // Assigns using a form any expression implicitly convertible to the single argument
426 // of a T's assignment operator.
427 // Converting assignments of optional<T> from optional<U> uses this function with
428 // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
429 template<class Expr>
430 void assign_expr_to_initialized ( Expr const& expr, void const* )
431 {
432 assign_value(expr);
433 }
434
435#endif
436
437#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
438 // BCB5.64 (and probably lower versions) workaround.
439 // The in-place factories are supported by means of catch-all constructors
440 // and assignment operators (the functions are parameterized in terms of
441 // an arbitrary 'Expr' type)
442 // This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U>
443 // to the 'Expr'-taking functions even though explicit overloads are present for them.
444 // Thus, the following overload is needed to properly handle the case when the 'lhs'
445 // is another optional.
446 //
447 // For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error
448 // instead of choosing the wrong overload
449 //
450#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
451 // Notice that 'Expr' will be optional<T> or optional<U> (but not tc_optional_base<..>)
452 template<class Expr>
453 void construct ( Expr&& expr, optional_tag const* )
454 {
455 if ( expr.is_initialized() )
456 {
457 // An exception can be thrown here.
458 // It it happens, THIS will be left uninitialized.
459 m_storage = value_type(boost::move(expr.get())) ;
460 m_initialized = true ;
461 }
462 }
463#else
464 // Notice that 'Expr' will be optional<T> or optional<U> (but not tc_optional_base<..>)
465 template<class Expr>
466 void construct ( Expr const& expr, optional_tag const* )
467 {
468 if ( expr.is_initialized() )
469 {
470 // An exception can be thrown here.
471 // It it happens, THIS will be left uninitialized.
472 m_storage = value_type(expr.get()) ;
473 m_initialized = true ;
474 }
475 }
476#endif
477#endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
478
479 void assign_value ( argument_type val ) { m_storage = val; }
480#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
481 void assign_value ( rval_reference_type val ) { m_storage = static_cast<rval_reference_type>(val); }
482#endif
483
484 void destroy()
485 {
486 m_initialized = false;
487 }
488
489 reference_const_type get_impl() const { return m_storage ; }
490 reference_type get_impl() { return m_storage ; }
491
492 pointer_const_type get_ptr_impl() const { return boost::addressof(m_storage); }
493 pointer_type get_ptr_impl() { return boost::addressof(m_storage); }
494
495 private :
496
497 bool m_initialized ;
498 T m_storage ;
499} ;
500