Line data Source code
1 : // trivilally-copyable version of the storage
2 :
3 : template<class T>
4 : class 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 0 : tc_optional_base()
26 : :
27 : m_initialized(false) {}
28 :
29 : tc_optional_base ( none_t )
30 : :
31 : m_initialized(false) {}
32 :
33 0 : tc_optional_base ( init_value_tag, 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 = 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 : // 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 0 : 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 0 : 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 : } ;
|