1 //-----------------------------------------------------------------------------
2 // boost variant/variant.hpp header file
3 // See http://www.boost.org for updates, documentation, and revision history.
4 //-----------------------------------------------------------------------------
5 //
6 // Copyright (c) 2002-2003 Eric Friedman, Itay Maman
7 // Copyright (c) 2012-2016 Antony Polukhin
8 //
9 // Distributed under the Boost Software License, Version 1.0. (See
10 // accompanying file LICENSE_1_0.txt or copy at
11 // http://www.boost.org/LICENSE_1_0.txt)
12
13 // Thanks to Adam Romanek for providing patches for exception-disabled env.
14
15 #ifndef BOOST_VARIANT_VARIANT_HPP
16 #define BOOST_VARIANT_VARIANT_HPP
17
18 #include <cstddef> // for std::size_t
19 #include <new> // for placement new
20
21 #include <boost/type_index.hpp>
22
23 #include <boost/variant/detail/config.hpp>
24 #include <boost/mpl/aux_/value_wknd.hpp>
25
26 #include <boost/variant/variant_fwd.hpp>
27 #include <boost/variant/detail/backup_holder.hpp>
28 #include <boost/variant/detail/enable_recursive_fwd.hpp>
29 #include <boost/variant/detail/forced_return.hpp>
30 #include <boost/variant/detail/initializer.hpp>
31 #include <boost/variant/detail/make_variant_list.hpp>
32 #include <boost/variant/detail/over_sequence.hpp>
33 #include <boost/variant/detail/visitation_impl.hpp>
34 #include <boost/variant/detail/hash_variant.hpp>
35
36 #include <boost/variant/detail/generic_result_type.hpp>
37 #include <boost/variant/detail/move.hpp>
38
39 #include <boost/detail/no_exceptions_support.hpp>
40 #include <boost/detail/reference_content.hpp>
41 #include <boost/aligned_storage.hpp>
42 #include <boost/blank.hpp>
43 #include <boost/math/common_factor_ct.hpp>
44 #include <boost/static_assert.hpp>
45 #include <boost/preprocessor/cat.hpp>
46 #include <boost/preprocessor/repeat.hpp>
47 #include <boost/type_traits/alignment_of.hpp>
48 #include <boost/type_traits/add_const.hpp>
49 #include <boost/type_traits/has_nothrow_constructor.hpp>
50 #include <boost/type_traits/has_nothrow_copy.hpp>
51 #include <boost/type_traits/is_nothrow_move_assignable.hpp>
52 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
53 #include <boost/type_traits/is_const.hpp>
54 #include <boost/type_traits/is_same.hpp>
55 #include <boost/type_traits/is_rvalue_reference.hpp>
56 #include <boost/type_traits/is_constructible.hpp>
57 #include <boost/type_traits/add_lvalue_reference.hpp>
58 #include <boost/utility/enable_if.hpp>
59 #include <boost/utility/declval.hpp>
60 #include <boost/variant/recursive_wrapper_fwd.hpp>
61 #include <boost/variant/static_visitor.hpp>
62
63 #include <boost/mpl/assert.hpp>
64 #include <boost/mpl/begin_end.hpp>
65 #include <boost/mpl/bool.hpp>
66 #include <boost/mpl/deref.hpp>
67 #include <boost/mpl/empty.hpp>
68 #include <boost/mpl/eval_if.hpp>
69 #include <boost/mpl/find_if.hpp>
70 #include <boost/mpl/fold.hpp>
71 #include <boost/mpl/front.hpp>
72 #include <boost/mpl/identity.hpp>
73 #include <boost/mpl/if.hpp>
74 #include <boost/mpl/insert_range.hpp>
75 #include <boost/mpl/int.hpp>
76 #include <boost/mpl/is_sequence.hpp>
77 #include <boost/mpl/iterator_range.hpp>
78 #include <boost/mpl/iter_fold_if.hpp>
79 #include <boost/mpl/list.hpp>
80 #include <boost/mpl/logical.hpp>
81 #include <boost/mpl/max_element.hpp>
82 #include <boost/mpl/next.hpp>
83 #include <boost/mpl/not.hpp>
84 #include <boost/mpl/pair.hpp>
85 #include <boost/mpl/protect.hpp>
86 #include <boost/mpl/push_front.hpp>
87 #include <boost/mpl/same_as.hpp>
88 #include <boost/mpl/size_t.hpp>
89 #include <boost/mpl/sizeof.hpp>
90 #include <boost/mpl/transform.hpp>
91
92 ///////////////////////////////////////////////////////////////////////////////
93 // Implementation Macros:
94 //
95 // BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
96 // Defined in boost/variant/detail/visitation_impl.hpp.
97 //
98 // BOOST_VARIANT_MINIMIZE_SIZE
99 // When #defined, implementation employs all known means to minimize the
100 // size of variant obje cts. However, often unsuccessful due to alignment
101 // issues, and potentially harmful to runtime speed, so not enabled by
102 // default. (TODO: Investigate further.)
103
104 #if defined(BOOST_VARIANT_MINIMIZE_SIZE)
105 # include <climits> // for SCHAR_MAX
106 # include <boost/mpl/eval_if.hpp>
107 # include <boost/mpl/equal_to.hpp>
108 # include <boost/mpl/identity.hpp>
109 # include <boost/mpl/int.hpp>
110 # include <boost/mpl/if.hpp>
111 # include <boost/mpl/less.hpp>
112 # include <boost/mpl/long.hpp>
113 # include <boost/mpl/O1_size.hpp>
114 #endif
115
116
117 namespace boost {
118
119 namespace detail { namespace variant {
120
121 ///////////////////////////////////////////////////////////////////////////////
122 // (detail) metafunction max_value
123 //
124 // Finds the maximum value of the unary metafunction F over Sequence.
125 //
126 template <typename Sequence, typename F>
127 struct max_value
128 {
129 private: // helpers, for metafunction result (below)
130
131 typedef typename mpl::transform1<Sequence, F>::type transformed_;
132 typedef typename mpl::max_element<transformed_
133
134 >::type max_it;
135
136 public: // metafunction result
137
138 typedef typename mpl::deref<max_it>::type
139 type;
140
141 };
142
143 struct add_alignment
144 {
145 template <typename State, typename Item>
146 struct apply
147 : mpl::size_t<
148 ::boost::math::static_lcm<
149 BOOST_MPL_AUX_VALUE_WKND(State)::value
150 , ::boost::alignment_of<Item>::value
151 >::value
152 >
153 {};
154 };
155
156 ///////////////////////////////////////////////////////////////////////////////
157 // (detail) metafunction find_fallback_type
158 //
159 // Provides a fallback (i.e., nothrow default-constructible) type from the
160 // specified sequence, or no_fallback_type if not found.
161 //
162 // This implementation is designed to prefer boost::blank over other potential
163 // fallback types, regardless of its position in the specified sequence.
164 //
165
166 class no_fallback_type;
167
168 struct find_fallback_type_pred
169 {
170 template <typename Iterator>
171 struct apply
172 {
173 private:
174 typedef typename mpl::deref<Iterator>::type t_;
175
176 public:
177 typedef mpl::not_< has_nothrow_constructor<t_> > type;
178 };
179 };
180
181 template <typename Types>
182 struct find_fallback_type
183 {
184 private: // helpers, for metafunction result (below)
185
186 typedef typename mpl::end<Types>::type end_it;
187
188 // [Find the first suitable fallback type...]
189
190 typedef typename mpl::iter_fold_if<
191 Types
192 , mpl::int_<0>, mpl::protect< mpl::next<> >
193 , mpl::protect< find_fallback_type_pred >
194 >::type first_result_;
195
196 typedef typename first_result_::first first_result_index;
197 typedef typename first_result_::second first_result_it;
198
199 // [...now search the rest of the sequence for boost::blank...]
200
201 typedef typename mpl::iter_fold_if<
202 mpl::iterator_range< first_result_it,end_it >
203 , first_result_index, mpl::protect< mpl::next<> >
204 , mpl::protect< mpl::not_same_as<boost::blank> >
205 >::type second_result_;
206
207 typedef typename second_result_::second second_result_it;
208
209 public: // metafunction result
210
211 // [...and return the results of the search:]
212 typedef typename mpl::eval_if<
213 is_same< second_result_it,end_it >
214 , mpl::if_<
215 is_same< first_result_it,end_it >
216 , mpl::pair< no_fallback_type,no_fallback_type >
217 , first_result_
218 >
219 , mpl::identity< second_result_ >
220 >::type type;
221
222 };
223
224 #ifndef BOOST_NO_CXX11_NOEXCEPT
225 ///////////////////////////////////////////////////////////////////////////////
226 // (detail) metafunction is_variant_move_noexcept_constructible
227 //
228 // Returns true_type if all the types are nothrow move constructible.
229 //
230 template <class Types>
231 struct is_variant_move_noexcept_constructible {
232 typedef typename boost::mpl::find_if<
233 Types, mpl::not_<boost::is_nothrow_move_constructible<boost::mpl::_1> >
234 >::type iterator_t;
235
236 typedef typename boost::mpl::end<Types>::type end_t;
237 typedef typename boost::is_same<
238 iterator_t, end_t
239 >::type type;
240 };
241
242 ///////////////////////////////////////////////////////////////////////////////
243 // (detail) metafunction is_variant_move_noexcept_assignable
244 //
245 // Returns true_type if all the types are nothrow move constructible.
246 //
247 template <class Types>
248 struct is_variant_move_noexcept_assignable {
249 typedef typename boost::mpl::find_if<
250 Types, mpl::not_<boost::is_nothrow_move_assignable<boost::mpl::_1> >
251 >::type iterator_t;
252
253 typedef typename boost::mpl::end<Types>::type end_t;
254 typedef typename boost::is_same<
255 iterator_t, end_t
256 >::type type;
257 };
258 #endif // BOOST_NO_CXX11_NOEXCEPT
259
260 ///////////////////////////////////////////////////////////////////////////////
261 // (detail) metafunction is_variant_constructible_from
262 //
263 // Derives from true_type if at least one variant's type is constructible from T.
264 //
265 template <class T1, class T2>
266 struct is_constructible_ext:
267 boost::mpl::or_<
268 boost::is_constructible<
269 T1,
270 T2
271 >,
272 boost::is_constructible<
273 T1,
274 typename boost::add_lvalue_reference<T2>::type
275 >
276 >
277 {};
278
279 template <class T, class Types>
280 struct is_variant_constructible_from:
281 boost::mpl::not_< boost::is_same<
282 typename boost::mpl::find_if<
283 Types,
284 is_constructible_ext<boost::mpl::_1, T>
285 >::type,
286 typename boost::mpl::end<Types>::type
287 > >
288 {};
289
290 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
291 struct is_variant_constructible_from< boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >:
292 boost::is_same<
293 typename boost::mpl::find_if<
294 typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::recursive_enabled_types,
295 mpl::not_< is_variant_constructible_from< boost::mpl::_1, Types> >
296 >::type,
297 typename boost::mpl::end< typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::recursive_enabled_types >::type
298 >
299 {};
300
301 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
302 struct is_variant_constructible_from< const boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& , Types >:
303 is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >
304 {};
305
306 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
307 struct is_variant_constructible_from< boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& , Types >:
308 is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >
309 {};
310
311 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
312
313 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
314 struct is_variant_constructible_from< boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>&& , Types >:
315 is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >
316 {};
317
318 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
319 struct is_variant_constructible_from< boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const && , Types >:
320 is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >
321 {};
322
323 #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCE
324
325
326 ///////////////////////////////////////////////////////////////////////////////
327 // (detail) metafunction make_storage
328 //
329 // Provides an aligned storage type capable of holding any of the types
330 // specified in the given type-sequence.
331 //
332
333 template <typename Types, typename NeverUsesBackupFlag>
334 struct make_storage
335 {
336 private: // helpers, for metafunction result (below)
337
338 typedef typename mpl::eval_if<
339 NeverUsesBackupFlag
340 , mpl::identity< Types >
341 , mpl::push_front<
342 Types, backup_holder<void*>
343 >
344 >::type types;
345
346 typedef typename max_value<
347 types, mpl::sizeof_<mpl::_1>
348 >::type max_size;
349
350 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
351
352 typedef typename mpl::fold<
353 types
354 , mpl::size_t<1>
355 , add_alignment
356 >::type max_alignment;
357
358 #else // borland
359
360 // temporary workaround -- use maximal alignment
361 typedef mpl::size_t< -1 > max_alignment;
362
363 #endif // borland workaround
364
365 public: // metafunction result
366
367 typedef ::boost::aligned_storage<
368 BOOST_MPL_AUX_VALUE_WKND(max_size)::value
369 , BOOST_MPL_AUX_VALUE_WKND(max_alignment)::value
370 > type;
371 };
372
373 ///////////////////////////////////////////////////////////////////////////////
374 // (detail) class destroyer
375 //
376 // Internal visitor that destroys the value it visits.
377 //
378 struct destroyer
379 : public static_visitor<>
380 {
381 public: // visitor interfaces
382
383 template <typename T>
384 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visitboost::detail::variant::destroyer385 internal_visit(T& operand, int) const BOOST_NOEXCEPT
386 {
387 operand.~T(); // must be noexcept
388
389 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551)) || \
390 BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
391 (void)operand; // suppresses warnings
392 #endif
393
394 BOOST_VARIANT_AUX_RETURN_VOID;
395 }
396
397 };
398
399 ///////////////////////////////////////////////////////////////////////////////
400 // (detail) class template known_get
401 //
402 // Visitor that returns a reference to content of the specified type.
403 //
404 // Precondition: visited variant MUST contain logical content of type T.
405 //
406 template <typename T>
407 class known_get
408 : public static_visitor<T&>
409 {
410
411 public: // visitor interface
412
operator ()(T & operand) const413 T& operator()(T& operand) const BOOST_NOEXCEPT
414 {
415 return operand;
416 }
417
418 template <typename U>
operator ()(U &) const419 T& operator()(U&) const
420 {
421 // logical error to be here: see precondition above
422 return ::boost::detail::variant::forced_return< T& >();
423 }
424 };
425
426 ///////////////////////////////////////////////////////////////////////////////
427 // (detail) class copy_into
428 //
429 // Internal visitor that copies the value it visits into the given buffer.
430 //
431 class copy_into
432 : public static_visitor<>
433 {
434 private: // representation
435
436 void* storage_;
437
438 public: // structors
439
copy_into(void * storage)440 explicit copy_into(void* storage) BOOST_NOEXCEPT
441 : storage_(storage)
442 {
443 }
444
445 public: // internal visitor interface
446
447 template <typename T>
448 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visit(boost::detail::variant::backup_holder<T> & operand,long) const449 internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
450 {
451 new(storage_) T( operand.get() );
452 BOOST_VARIANT_AUX_RETURN_VOID;
453 }
454
455 template <typename T>
456 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visit(const boost::detail::variant::backup_holder<T> & operand,long) const457 internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
458 {
459 new(storage_) T( operand.get() );
460 BOOST_VARIANT_AUX_RETURN_VOID;
461 }
462
463 template <typename T>
464 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visit(const T & operand,int) const465 internal_visit(const T& operand, int) const
466 {
467 new(storage_) T(operand);
468 BOOST_VARIANT_AUX_RETURN_VOID;
469 }
470
471 };
472
473 ///////////////////////////////////////////////////////////////////////////////
474 // (detail) class move_into
475 //
476 // Internal visitor that moves the value it visits into the given buffer.
477 //
478 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
479 class move_into
480 : public static_visitor<>
481 {
482 private: // representation
483
484 void* storage_;
485
486 public: // structors
487
move_into(void * storage)488 explicit move_into(void* storage) BOOST_NOEXCEPT
489 : storage_(storage)
490 {
491 }
492
493 public: // internal visitor interface
494
495 template <typename T>
496 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visit(boost::detail::variant::backup_holder<T> & operand,long) const497 internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
498 {
499 new(storage_) T( ::boost::detail::variant::move(operand.get()) );
500 BOOST_VARIANT_AUX_RETURN_VOID;
501 }
502
503 template <typename T>
504 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visit(T & operand,int) const505 internal_visit(T& operand, int) const BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(boost::declval<T>())))
506 {
507 new(storage_) T(::boost::detail::variant::move(operand));
508 BOOST_VARIANT_AUX_RETURN_VOID;
509 }
510 };
511 #endif
512
513 ///////////////////////////////////////////////////////////////////////////////
514 // (detail) class assign_storage
515 //
516 // Internal visitor that assigns the given storage (which must be a
517 // constructed value of the same type) to the value it visits.
518 //
519 struct assign_storage
520 : public static_visitor<>
521 {
522 private: // representation
523
524 const void* rhs_storage_;
525
526 public: // structors
527
assign_storageboost::detail::variant::assign_storage528 explicit assign_storage(const void* rhs_storage) BOOST_NOEXCEPT
529 : rhs_storage_(rhs_storage)
530 {
531 }
532
533 public: // internal visitor interfaces
534
535 template <typename T>
536 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visitboost::detail::variant::assign_storage537 internal_visit(backup_holder<T>& lhs_content, long) const
538 {
539 lhs_content.get()
540 = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
541 BOOST_VARIANT_AUX_RETURN_VOID;
542 }
543
544 template <typename T>
545 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visitboost::detail::variant::assign_storage546 internal_visit(const backup_holder<T>& lhs_content, long) const
547 {
548 lhs_content.get()
549 = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
550 BOOST_VARIANT_AUX_RETURN_VOID;
551 }
552
553 template <typename T>
554 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visitboost::detail::variant::assign_storage555 internal_visit(T& lhs_content, int) const
556 {
557 // NOTE TO USER :
558 // Compile error here indicates one of variant's bounded types does
559 // not meet the requirements of the Assignable concept. Thus,
560 // variant is not Assignable.
561 //
562 // Hint: Are any of the bounded types const-qualified or references?
563 //
564 lhs_content = *static_cast< const T* >(rhs_storage_);
565 BOOST_VARIANT_AUX_RETURN_VOID;
566 }
567
568 };
569
570 ///////////////////////////////////////////////////////////////////////////////
571 // (detail) class move_storage
572 //
573 // Internal visitor that moves the given storage (which must be a
574 // constructed value of the same type) to the value it visits.
575 //
576 struct move_storage
577 : public static_visitor<>
578 {
579 private: // representation
580
581 void* rhs_storage_;
582
583 public: // structors
584
move_storageboost::detail::variant::move_storage585 explicit move_storage(void* rhs_storage) BOOST_NOEXCEPT
586 : rhs_storage_(rhs_storage)
587 {
588 }
589
590 public: // internal visitor interfaces
591
592 template <typename T>
593 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visitboost::detail::variant::move_storage594 internal_visit(backup_holder<T>& lhs_content, long) const
595 {
596 lhs_content.get()
597 = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
598 BOOST_VARIANT_AUX_RETURN_VOID;
599 }
600
601 template <typename T>
602 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visitboost::detail::variant::move_storage603 internal_visit(const backup_holder<T>& lhs_content, long) const
604 {
605 lhs_content.get()
606 = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
607 BOOST_VARIANT_AUX_RETURN_VOID;
608 }
609
610 template <typename T>
611 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visitboost::detail::variant::move_storage612 internal_visit(T& lhs_content, int) const
613 {
614 // NOTE TO USER :
615 // Compile error here indicates one of variant's bounded types does
616 // not meet the requirements of the Assignable concept. Thus,
617 // variant is not Assignable.
618 //
619 // Hint: Are any of the bounded types const-qualified or references?
620 //
621 lhs_content = ::boost::detail::variant::move(*static_cast<T* >(rhs_storage_));
622 BOOST_VARIANT_AUX_RETURN_VOID;
623 }
624
625 };
626
627 ///////////////////////////////////////////////////////////////////////////////
628 // (detail) class direct_assigner
629 //
630 // Generic static visitor that: if and only if the visited value is of the
631 // specified type, assigns the given value to the visited value and returns
632 // true; else returns false.
633 //
634 template <typename T>
635 class direct_assigner
636 : public static_visitor<bool>
637 {
638 private: // representation
639
640 const T& rhs_;
641
642 public: // structors
643
direct_assigner(const T & rhs)644 explicit direct_assigner(const T& rhs) BOOST_NOEXCEPT
645 : rhs_(rhs)
646 {
647 }
648
649 public: // visitor interface
650
operator ()(T & lhs)651 bool operator()(T& lhs)
652 {
653 lhs = rhs_;
654 return true;
655 }
656
657 template <typename U>
operator ()(U &)658 bool operator()(U&) BOOST_NOEXCEPT
659 {
660 return false;
661 }
662
663 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
664 private:
665 // silence MSVC warning C4512: assignment operator could not be generated
666 direct_assigner& operator= (direct_assigner const&);
667 #endif
668 };
669
670 ///////////////////////////////////////////////////////////////////////////////
671 // (detail) class direct_mover
672 //
673 // Generic static visitor that: if and only if the visited value is of the
674 // specified type, move assigns the given value to the visited value and returns
675 // true; else returns false.
676 //
677 template <typename T>
678 class direct_mover
679 : public static_visitor<bool>
680 {
681 private: // representation
682
683 T& rhs_;
684
685 public: // structors
686
direct_mover(T & rhs)687 explicit direct_mover(T& rhs) BOOST_NOEXCEPT
688 : rhs_(rhs)
689 {
690 }
691
692 public: // visitor interface
693
operator ()(T & lhs)694 bool operator()(T& lhs)
695 {
696 lhs = ::boost::detail::variant::move(rhs_);
697 return true;
698 }
699
700 template <typename U>
operator ()(U &)701 bool operator()(U&) BOOST_NOEXCEPT
702 {
703 return false;
704 }
705
706 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
707 private:
708 // silence MSVC warning C4512: assignment operator could not be generated
709 direct_mover& operator= (direct_mover const&);
710 #endif
711 };
712
713
714 ///////////////////////////////////////////////////////////////////////////////
715 // (detail) class backup_assigner
716 //
717 // Internal visitor that "assigns" the given value to the visited value,
718 // using backup to recover if the destroy-copy sequence fails.
719 //
720 // NOTE: This needs to be a friend of variant, as it needs access to
721 // indicate_which, indicate_backup_which, etc.
722 //
723 template <typename Variant>
724 class backup_assigner
725 : public static_visitor<>
726 {
727 private: // representation
728
729 Variant& lhs_;
730 int rhs_which_;
731 const void* rhs_content_;
732 void (*copy_rhs_content_)(void*, const void*);
733
734 public: // structors
735
736 template<class RhsT>
backup_assigner(Variant & lhs,int rhs_which,const RhsT & rhs_content)737 backup_assigner(Variant& lhs, int rhs_which, const RhsT& rhs_content)
738 : lhs_(lhs)
739 , rhs_which_(rhs_which)
740 , rhs_content_(&rhs_content)
741 , copy_rhs_content_(&construct_impl<RhsT>)
742 {
743 }
744
745 private: // helpers, for visitor interface (below)
746
747 template<class RhsT>
construct_impl(void * addr,const void * obj)748 static void construct_impl(void* addr, const void* obj)
749 {
750 new(addr) RhsT(*static_cast<const RhsT*>(obj));
751 }
752
753 template <typename LhsT>
backup_assign_impl(backup_holder<LhsT> & lhs_content,mpl::false_,long)754 void backup_assign_impl(
755 backup_holder<LhsT>& lhs_content
756 , mpl::false_ // is_nothrow_move_constructible
757 , long
758 )
759 {
760 // Move lhs content to backup...
761 backup_holder<LhsT> backup_lhs_content(0);
762 backup_lhs_content.swap(lhs_content); // nothrow
763
764 // ...destroy lhs content...
765 lhs_content.~backup_holder<LhsT>(); // nothrow
766
767 BOOST_TRY
768 {
769 // ...and attempt to copy rhs content into lhs storage:
770 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
771 }
772 BOOST_CATCH (...)
773 {
774 // In case of failure, copy backup pointer to lhs storage...
775 new(lhs_.storage_.address())
776 backup_holder<LhsT>( 0 ); // nothrow
777
778 static_cast<backup_holder<LhsT>* >(lhs_.storage_.address())
779 ->swap(backup_lhs_content); // nothrow
780
781 // ...and rethrow:
782 BOOST_RETHROW;
783 }
784 BOOST_CATCH_END
785
786 // In case of success, indicate new content type:
787 lhs_.indicate_which(rhs_which_); // nothrow
788 }
789
790 template <typename LhsT>
backup_assign_impl(LhsT & lhs_content,mpl::true_,int)791 void backup_assign_impl(
792 LhsT& lhs_content
793 , mpl::true_ // is_nothrow_move_constructible
794 , int
795 )
796 {
797 // Move lhs content to backup...
798 LhsT backup_lhs_content(
799 ::boost::detail::variant::move(lhs_content)
800 ); // nothrow
801
802 // ...destroy lhs content...
803 lhs_content.~LhsT(); // nothrow
804
805 BOOST_TRY
806 {
807 // ...and attempt to copy rhs content into lhs storage:
808 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
809 }
810 BOOST_CATCH (...)
811 {
812 // In case of failure, restore backup content to lhs storage...
813 new(lhs_.storage_.address())
814 LhsT(
815 ::boost::detail::variant::move(backup_lhs_content)
816 ); // nothrow
817
818 // ...and rethrow:
819 BOOST_RETHROW;
820 }
821 BOOST_CATCH_END
822
823 // In case of success, indicate new content type:
824 lhs_.indicate_which(rhs_which_); // nothrow
825 }
826
827 template <typename LhsT>
backup_assign_impl(LhsT & lhs_content,mpl::false_,int)828 void backup_assign_impl(
829 LhsT& lhs_content
830 , mpl::false_ // is_nothrow_move_constructible
831 , int
832 )
833 {
834 // Backup lhs content...
835 LhsT* backup_lhs_ptr = new LhsT(lhs_content);
836
837 // ...destroy lhs content...
838 lhs_content.~LhsT(); // nothrow
839
840 BOOST_TRY
841 {
842 // ...and attempt to copy rhs content into lhs storage:
843 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
844 }
845 BOOST_CATCH (...)
846 {
847 // In case of failure, copy backup pointer to lhs storage...
848 new(lhs_.storage_.address())
849 backup_holder<LhsT>( backup_lhs_ptr ); // nothrow
850
851 // ...indicate now using backup...
852 lhs_.indicate_backup_which( lhs_.which() ); // nothrow
853
854 // ...and rethrow:
855 BOOST_RETHROW;
856 }
857 BOOST_CATCH_END
858
859 // In case of success, indicate new content type...
860 lhs_.indicate_which(rhs_which_); // nothrow
861
862 // ...and delete backup:
863 delete backup_lhs_ptr; // nothrow
864 }
865
866 public: // visitor interface
867
868 template <typename LhsT>
869 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visit(LhsT & lhs_content,int)870 internal_visit(LhsT& lhs_content, int)
871 {
872 typedef typename is_nothrow_move_constructible<LhsT>::type
873 nothrow_move;
874
875 backup_assign_impl( lhs_content, nothrow_move(), 1L);
876
877 BOOST_VARIANT_AUX_RETURN_VOID;
878 }
879
880 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
881 private:
882 // silence MSVC warning C4512: assignment operator could not be generated
883 backup_assigner& operator= (backup_assigner const&);
884 #endif
885 };
886
887 ///////////////////////////////////////////////////////////////////////////////
888 // (detail) class swap_with
889 //
890 // Visitor that swaps visited value with content of given variant.
891 //
892 // Precondition: Given variant MUST have same logical type as visited value.
893 //
894 template <typename Variant>
895 struct swap_with
896 : public static_visitor<>
897 {
898 private: // representation
899
900 Variant& toswap_;
901
902 public: // structors
903
swap_withboost::detail::variant::swap_with904 explicit swap_with(Variant& toswap) BOOST_NOEXCEPT
905 : toswap_(toswap)
906 {
907 }
908
909 public: // internal visitor interfaces
910
911 template <typename T>
operator ()boost::detail::variant::swap_with912 void operator()(T& operand) const
913 {
914 // Since the precondition ensures types are same, get T...
915 known_get<T> getter;
916 T& other = toswap_.apply_visitor(getter);
917
918 // ...and swap:
919 ::boost::detail::variant::move_swap( operand, other );
920 }
921
922 private:
923 swap_with& operator=(const swap_with&);
924
925 };
926
927 ///////////////////////////////////////////////////////////////////////////////
928 // (detail) class reflect
929 //
930 // Generic static visitor that performs a typeid on the value it visits.
931 //
932
933 class reflect
934 : public static_visitor<const boost::typeindex::type_info&>
935 {
936 public: // visitor interfaces
937
938 template <typename T>
operator ()(const T &) const939 const boost::typeindex::type_info& operator()(const T&) const BOOST_NOEXCEPT
940 {
941 return boost::typeindex::type_id<T>().type_info();
942 }
943
944 };
945
946 ///////////////////////////////////////////////////////////////////////////////
947 // (detail) class comparer
948 //
949 // Generic static visitor that compares the content of the given lhs variant
950 // with the visited rhs content using Comp.
951 //
952 // Precondition: lhs.which() == rhs.which()
953 //
954 template <typename Variant, typename Comp>
955 class comparer
956 : public static_visitor<bool>
957 {
958 private: // representation
959
960 const Variant& lhs_;
961
962 public: // structors
963
comparer(const Variant & lhs)964 explicit comparer(const Variant& lhs) BOOST_NOEXCEPT
965 : lhs_(lhs)
966 {
967 }
968
969 public: // visitor interfaces
970
971 template <typename T>
operator ()(T & rhs_content) const972 bool operator()(T& rhs_content) const
973 {
974 // Since the precondition ensures lhs and rhs types are same, get T...
975 known_get<T> getter;
976 const T& lhs_content = lhs_.apply_visitor(getter);
977
978 // ...and compare lhs and rhs contents:
979 return Comp()(lhs_content, rhs_content);
980 }
981
982 private:
983 comparer& operator=(const comparer&);
984
985 };
986
987 ///////////////////////////////////////////////////////////////////////////////
988 // (detail) class equal_comp
989 //
990 // Generic function object compares lhs with rhs using operator==.
991 //
992 struct equal_comp
993 {
994 template <typename T>
operator ()boost::detail::variant::equal_comp995 bool operator()(const T& lhs, const T& rhs) const
996 {
997 return lhs == rhs;
998 }
999 };
1000
1001 ///////////////////////////////////////////////////////////////////////////////
1002 // (detail) class less_comp
1003 //
1004 // Generic function object compares lhs with rhs using operator<.
1005 //
1006 struct less_comp
1007 {
1008 template <typename T>
operator ()boost::detail::variant::less_comp1009 bool operator()(const T& lhs, const T& rhs) const
1010 {
1011 return lhs < rhs;
1012 }
1013 };
1014
1015 ///////////////////////////////////////////////////////////////////////////////
1016 // (detail) class template invoke_visitor
1017 //
1018 // Internal visitor that invokes the given visitor using:
1019 // * for wrappers (e.g., recursive_wrapper), the wrapper's held value.
1020 // * for all other values, the value itself.
1021 //
1022 template <typename Visitor>
1023 class invoke_visitor
1024 {
1025 private: // representation
1026
1027 Visitor& visitor_;
1028
1029 public: // visitor typedefs
1030
1031 typedef typename Visitor::result_type
1032 result_type;
1033
1034 public: // structors
1035
invoke_visitor(Visitor & visitor)1036 explicit invoke_visitor(Visitor& visitor) BOOST_NOEXCEPT
1037 : visitor_(visitor)
1038 {
1039 }
1040
1041 #if !defined(BOOST_NO_VOID_RETURNS)
1042
1043 public: // internal visitor interfaces
1044
1045 template <typename T>
internal_visit(T & operand,int)1046 result_type internal_visit(T& operand, int)
1047 {
1048 return visitor_(operand);
1049 }
1050
1051 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
1052 template <typename T>
internal_visit(const T & operand,int)1053 result_type internal_visit(const T& operand, int)
1054 {
1055 return visitor_(operand);
1056 }
1057 # endif
1058
1059 #else // defined(BOOST_NO_VOID_RETURNS)
1060
1061 private: // helpers, for internal visitor interfaces (below)
1062
1063 template <typename T>
1064 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
visit_impl(T & operand,mpl::false_)1065 visit_impl(T& operand, mpl::false_)
1066 {
1067 return visitor_(operand);
1068 }
1069
1070 template <typename T>
1071 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
visit_impl(T & operand,mpl::true_)1072 visit_impl(T& operand, mpl::true_)
1073 {
1074 visitor_(operand);
1075 BOOST_VARIANT_AUX_RETURN_VOID;
1076 }
1077
1078 public: // internal visitor interfaces
1079
1080 template <typename T>
1081 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
internal_visit(T & operand,int)1082 internal_visit(T& operand, int)
1083 {
1084 typedef typename is_same<result_type, void>::type
1085 has_void_result_type;
1086
1087 return visit_impl(operand, has_void_result_type());
1088 }
1089
1090 #endif // BOOST_NO_VOID_RETURNS) workaround
1091
1092 public: // internal visitor interfaces, cont.
1093
1094 template <typename T>
1095 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
internal_visit(boost::recursive_wrapper<T> & operand,long)1096 internal_visit(boost::recursive_wrapper<T>& operand, long)
1097 {
1098 return internal_visit( operand.get(), 1L );
1099 }
1100
1101 template <typename T>
1102 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
internal_visit(const boost::recursive_wrapper<T> & operand,long)1103 internal_visit(const boost::recursive_wrapper<T>& operand, long)
1104 {
1105 return internal_visit( operand.get(), 1L );
1106 }
1107
1108 template <typename T>
1109 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
internal_visit(boost::detail::reference_content<T> & operand,long)1110 internal_visit(boost::detail::reference_content<T>& operand, long)
1111 {
1112 return internal_visit( operand.get(), 1L );
1113 }
1114
1115 template <typename T>
1116 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
internal_visit(const boost::detail::reference_content<T> & operand,long)1117 internal_visit(const boost::detail::reference_content<T>& operand, long)
1118 {
1119 return internal_visit( operand.get(), 1L );
1120 }
1121
1122 template <typename T>
1123 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
internal_visit(boost::detail::variant::backup_holder<T> & operand,long)1124 internal_visit(boost::detail::variant::backup_holder<T>& operand, long)
1125 {
1126 return internal_visit( operand.get(), 1L );
1127 }
1128
1129 template <typename T>
1130 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
internal_visit(const boost::detail::variant::backup_holder<T> & operand,long)1131 internal_visit(const boost::detail::variant::backup_holder<T>& operand, long)
1132 {
1133 return internal_visit( operand.get(), 1L );
1134 }
1135
1136 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
1137 private:
1138 // silence MSVC warning C4512: assignment operator could not be generated
1139 invoke_visitor& operator= (invoke_visitor const&);
1140 #endif
1141 };
1142
1143 }} // namespace detail::variant
1144
1145 ///////////////////////////////////////////////////////////////////////////////
1146 // class template variant (concept inspired by Andrei Alexandrescu)
1147 //
1148 // See docs and boost/variant/variant_fwd.hpp for more information.
1149 //
1150 template <
1151 typename T0_
1152 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)
1153 >
1154 class variant
1155 {
1156 private: // helpers, for typedefs (below)
1157
1158 typedef variant wknd_self_t;
1159
1160 struct is_recursive_
1161 : detail::variant::is_recursive_flag<T0_>
1162 {
1163 };
1164
1165 typedef typename mpl::eval_if<
1166 is_recursive_
1167 , T0_
1168 , mpl::identity< T0_ >
1169 >::type unwrapped_T0_;
1170
1171 struct is_sequence_based_
1172 : detail::variant::is_over_sequence<unwrapped_T0_>
1173 {
1174 };
1175
1176 #if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
1177
1178 private: // helpers, for typedefs (below)
1179
1180 typedef typename mpl::eval_if<
1181 is_sequence_based_
1182 , unwrapped_T0_ // over_sequence<...>::type
1183 , detail::variant::make_variant_list<
1184 unwrapped_T0_
1185 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
1186 >
1187 >::type specified_types;
1188
1189 BOOST_STATIC_ASSERT((
1190 ::boost::mpl::not_< mpl::empty<specified_types> >::value
1191 ));
1192
1193 public: // public typedefs
1194 typedef typename mpl::eval_if<
1195 is_recursive_
1196 , mpl::transform<
1197 specified_types
1198 , mpl::protect<
1199 detail::variant::quoted_enable_recursive<wknd_self_t>
1200 >
1201 >
1202 , mpl::identity< specified_types >
1203 >::type recursive_enabled_types; // used by is_variant_constructible_from<> trait
1204
1205 typedef typename mpl::transform<
1206 recursive_enabled_types
1207 , unwrap_recursive<mpl::_1>
1208 >::type types;
1209
1210 private: // internal typedefs
1211
1212 typedef typename mpl::transform<
1213 recursive_enabled_types
1214 , mpl::protect< detail::make_reference_content<> >
1215 >::type internal_types;
1216
1217 typedef typename mpl::front<
1218 internal_types
1219 >::type internal_T0;
1220
1221 #else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
1222
1223 private: // helpers, for typedefs (below)
1224
1225 typedef unwrapped_T0_ T0;
1226
1227 #define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
1228 typedef typename mpl::eval_if< \
1229 is_recursive_ \
1230 , detail::variant::enable_recursive< \
1231 BOOST_PP_CAT(T,N) \
1232 , wknd_self_t \
1233 > \
1234 , mpl::identity< BOOST_PP_CAT(T,N) > \
1235 >::type BOOST_PP_CAT(recursive_enabled_T,N); \
1236 /**/
1237
1238 BOOST_PP_REPEAT(
1239 BOOST_VARIANT_LIMIT_TYPES
1240 , BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1241 , _
1242 )
1243
1244 #undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1245
1246 #define BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS(z,N,_) \
1247 typedef typename unwrap_recursive< \
1248 BOOST_PP_CAT(recursive_enabled_T,N) \
1249 >::type BOOST_PP_CAT(public_T,N); \
1250 /**/
1251
1252 BOOST_PP_REPEAT(
1253 BOOST_VARIANT_LIMIT_TYPES
1254 , BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1255 , _
1256 )
1257
1258 #undef BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1259
1260 public: // public typedefs
1261
1262 typedef typename detail::variant::make_variant_list<
1263 BOOST_VARIANT_ENUM_PARAMS(public_T)
1264 >::type types;
1265
1266 private: // helpers, for internal typedefs (below)
1267
1268 #define BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS(z,N,_) \
1269 typedef detail::make_reference_content< \
1270 BOOST_PP_CAT(recursive_enabled_T,N) \
1271 >::type BOOST_PP_CAT(internal_T,N); \
1272 /**/
1273
1274 BOOST_PP_REPEAT(
1275 BOOST_VARIANT_LIMIT_TYPES
1276 , BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1277 , _
1278 )
1279
1280 #undef BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1281
1282 private: // internal typedefs
1283
1284 typedef typename detail::variant::make_variant_list<
1285 BOOST_VARIANT_ENUM_PARAMS(internal_T)
1286 >::type internal_types;
1287
1288 private: // static precondition assertions
1289
1290 // NOTE TO USER :
1291 // variant< type-sequence > syntax is not supported on this compiler!
1292 //
1293 BOOST_MPL_ASSERT_NOT(( is_sequence_based_ ));
1294
1295 #endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT workaround
1296
1297 private: // helpers, for representation (below)
1298
1299 typedef typename detail::variant::find_fallback_type<
1300 internal_types
1301 >::type fallback_type_result_;
1302
1303 typedef typename fallback_type_result_::first
1304 fallback_type_index_;
1305 typedef typename fallback_type_result_::second
1306 fallback_type_;
1307
1308 struct has_fallback_type_
1309 : mpl::not_<
1310 is_same< fallback_type_, detail::variant::no_fallback_type >
1311 >
1312 {
1313 };
1314
1315 typedef has_fallback_type_
1316 never_uses_backup_flag;
1317
1318 typedef typename detail::variant::make_storage<
1319 internal_types, never_uses_backup_flag
1320 >::type storage_t;
1321
1322 #ifndef BOOST_NO_CXX11_NOEXCEPT
1323 typedef typename detail::variant::is_variant_move_noexcept_constructible<
1324 internal_types
1325 > variant_move_noexcept_constructible;
1326
1327 typedef typename detail::variant::is_variant_move_noexcept_assignable<
1328 internal_types
1329 > variant_move_noexcept_assignable;
1330
1331 #endif
1332
1333 private: // helpers, for representation (below)
1334
1335 // which_ on:
1336 // * [0, size<internal_types>) indicates stack content
1337 // * [-size<internal_types>, 0) indicates pointer to heap backup
1338 // if which_ >= 0:
1339 // * then which() -> which_
1340 // * else which() -> -(which_ + 1)
1341
1342 #if !defined(BOOST_VARIANT_MINIMIZE_SIZE)
1343
1344 typedef int which_t;
1345
1346 #else // defined(BOOST_VARIANT_MINIMIZE_SIZE)
1347
1348 // [if O1_size available, then attempt which_t size optimization...]
1349 // [select signed char if fewer than SCHAR_MAX types, else signed int:]
1350 typedef typename mpl::eval_if<
1351 mpl::equal_to< mpl::O1_size<internal_types>, mpl::long_<-1> >
1352 , mpl::identity< int >
1353 , mpl::if_<
1354 mpl::less< mpl::O1_size<internal_types>, mpl::int_<SCHAR_MAX> >
1355 , signed char
1356 , int
1357 >
1358 >::type which_t;
1359
1360 #endif // BOOST_VARIANT_MINIMIZE_SIZE switch
1361
1362 // representation -- private when possible
1363 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1364 private:
1365 #else
1366 public:
1367 #endif
1368
1369 which_t which_;
1370 storage_t storage_;
1371
indicate_which(int which_arg)1372 void indicate_which(int which_arg) BOOST_NOEXCEPT
1373 {
1374 which_ = static_cast<which_t>( which_arg );
1375 }
1376
indicate_backup_which(int which_arg)1377 void indicate_backup_which(int which_arg) BOOST_NOEXCEPT
1378 {
1379 which_ = static_cast<which_t>( -(which_arg + 1) );
1380 }
1381
1382 private: // helpers, for queries (below)
1383
using_backup() const1384 bool using_backup() const BOOST_NOEXCEPT
1385 {
1386 return which_ < 0;
1387 }
1388
1389 public: // queries
1390
which() const1391 int which() const BOOST_NOEXCEPT
1392 {
1393 // If using heap backup...
1394 if (using_backup())
1395 // ...then return adjusted which_:
1396 return -(which_ + 1);
1397
1398 // Otherwise, return which_ directly:
1399 return which_;
1400 }
1401
1402 private: // helpers, for structors (below)
1403
1404 struct initializer
1405 : BOOST_VARIANT_AUX_INITIALIZER_T(
1406 recursive_enabled_types, recursive_enabled_T
1407 )
1408 {
1409 };
1410
destroy_content()1411 void destroy_content() BOOST_NOEXCEPT
1412 {
1413 detail::variant::destroyer visitor;
1414 this->internal_apply_visitor(visitor);
1415 }
1416
1417 public: // structors
1418
~variant()1419 ~variant() BOOST_NOEXCEPT
1420 {
1421 destroy_content();
1422 }
1423
1424 variant()
1425 #if !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130))
BOOST_NOEXCEPT_IF(boost::has_nothrow_constructor<internal_T0>::value)1426 BOOST_NOEXCEPT_IF(boost::has_nothrow_constructor<internal_T0>::value)
1427 #endif
1428 {
1429 #ifdef _MSC_VER
1430 #pragma warning( push )
1431 // behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized
1432 #pragma warning( disable : 4345 )
1433 #endif
1434 // NOTE TO USER :
1435 // Compile error from here indicates that the first bound
1436 // type is not default-constructible, and so variant cannot
1437 // support its own default-construction.
1438 //
1439 new( storage_.address() ) internal_T0();
1440 indicate_which(0); // zero is the index of the first bounded type
1441 #ifdef _MSC_VER
1442 #pragma warning( pop )
1443 #endif
1444 }
1445
1446 private: // helpers, for structors, cont. (below)
1447
1448 class convert_copy_into
1449 : public static_visitor<int>
1450 {
1451 private: // representation
1452
1453 void* storage_;
1454
1455 public: // structors
1456
convert_copy_into(void * storage)1457 explicit convert_copy_into(void* storage) BOOST_NOEXCEPT
1458 : storage_(storage)
1459 {
1460 }
1461
1462 public: // internal visitor interfaces (below)
1463
1464 template <typename T>
internal_visit(T & operand,int) const1465 int internal_visit(T& operand, int) const
1466 {
1467 // NOTE TO USER :
1468 // Compile error here indicates one of the source variant's types
1469 // cannot be unambiguously converted to the destination variant's
1470 // types (or that no conversion exists).
1471 //
1472 return initializer::initialize(storage_, operand);
1473 }
1474
1475 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
1476 template <typename T>
internal_visit(const T & operand,int) const1477 result_type internal_visit(const T& operand, int) const
1478 {
1479 return initializer::initialize(storage_, operand);
1480 }
1481 # endif
1482
1483 template <typename T>
internal_visit(boost::detail::reference_content<T> & operand,long) const1484 int internal_visit(boost::detail::reference_content<T>& operand, long) const
1485 {
1486 return internal_visit( operand.get(), 1L );
1487 }
1488
1489 template <typename T>
internal_visit(const boost::detail::reference_content<T> & operand,long) const1490 int internal_visit(const boost::detail::reference_content<T>& operand, long) const
1491 {
1492 return internal_visit( operand.get(), 1L );
1493 }
1494
1495 template <typename T>
internal_visit(boost::detail::variant::backup_holder<T> & operand,long) const1496 int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
1497 {
1498 return internal_visit( operand.get(), 1L );
1499 }
1500
1501 template <typename T>
internal_visit(const boost::detail::variant::backup_holder<T> & operand,long) const1502 int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
1503 {
1504 return internal_visit( operand.get(), 1L );
1505 }
1506
1507 template <typename T>
internal_visit(boost::recursive_wrapper<T> & operand,long) const1508 int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1509 {
1510 return internal_visit( operand.get(), 1L );
1511 }
1512
1513 template <typename T>
internal_visit(const boost::recursive_wrapper<T> & operand,long) const1514 int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
1515 {
1516 return internal_visit( operand.get(), 1L );
1517 }
1518
1519 };
1520
1521 friend class convert_copy_into;
1522
1523 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1524 class convert_move_into
1525 : public static_visitor<int>
1526 {
1527 private: // representation
1528
1529 void* storage_;
1530
1531 public: // structors
1532
convert_move_into(void * storage)1533 explicit convert_move_into(void* storage) BOOST_NOEXCEPT
1534 : storage_(storage)
1535 {
1536 }
1537
1538 public: // internal visitor interfaces (below)
1539
1540 template <typename T>
internal_visit(T & operand,int) const1541 int internal_visit(T& operand, int) const
1542 {
1543 // NOTE TO USER :
1544 // Compile error here indicates one of the source variant's types
1545 // cannot be unambiguously converted to the destination variant's
1546 // types (or that no conversion exists).
1547 //
1548 return initializer::initialize(storage_, detail::variant::move(operand) );
1549 }
1550
1551 template <typename T>
internal_visit(boost::detail::reference_content<T> & operand,long) const1552 int internal_visit(boost::detail::reference_content<T>& operand, long) const
1553 {
1554 return internal_visit( operand.get(), 1L );
1555 }
1556
1557 template <typename T>
internal_visit(const boost::detail::reference_content<T> & operand,long) const1558 int internal_visit(const boost::detail::reference_content<T>& operand, long) const
1559 {
1560 return internal_visit( operand.get(), 1L );
1561 }
1562
1563 template <typename T>
internal_visit(boost::detail::variant::backup_holder<T> & operand,long) const1564 int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
1565 {
1566 return internal_visit( operand.get(), 1L );
1567 }
1568
1569 template <typename T>
internal_visit(const boost::detail::variant::backup_holder<T> & operand,long) const1570 int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
1571 {
1572 return internal_visit( operand.get(), 1L );
1573 }
1574
1575 template <typename T>
internal_visit(boost::recursive_wrapper<T> & operand,long) const1576 int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1577 {
1578 return internal_visit( operand.get(), 1L );
1579 }
1580
1581 template <typename T>
internal_visit(const boost::recursive_wrapper<T> & operand,long) const1582 int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
1583 {
1584 return internal_visit( operand.get(), 1L );
1585 }
1586 };
1587
1588 friend class convert_move_into;
1589 #endif
1590
1591 private: // helpers, for structors, below
1592
1593 template <typename T>
convert_construct(T & operand,int,mpl::false_=mpl::false_ ())1594 void convert_construct(
1595 T& operand
1596 , int
1597 , mpl::false_ = mpl::false_() // is_foreign_variant
1598 )
1599 {
1600 // NOTE TO USER :
1601 // Compile error here indicates that the given type is not
1602 // unambiguously convertible to one of the variant's types
1603 // (or that no conversion exists).
1604 //
1605 indicate_which(
1606 initializer::initialize(
1607 storage_.address()
1608 , operand
1609 )
1610 );
1611 }
1612
1613 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1614 template <typename T>
convert_construct(T && operand,int,mpl::false_=mpl::false_ ())1615 typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type convert_construct(
1616 T&& operand
1617 , int
1618 , mpl::false_ = mpl::false_() // is_foreign_variant
1619 )
1620 {
1621 // NOTE TO USER :
1622 // Compile error here indicates that the given type is not
1623 // unambiguously convertible to one of the variant's types
1624 // (or that no conversion exists).
1625 //
1626 indicate_which(
1627 initializer::initialize(
1628 storage_.address()
1629 , detail::variant::move(operand)
1630 )
1631 );
1632 }
1633 #endif
1634
1635 template <typename Variant>
convert_construct(Variant & operand,long,mpl::true_)1636 void convert_construct(
1637 Variant& operand
1638 , long
1639 , mpl::true_// is_foreign_variant
1640 )
1641 {
1642 convert_copy_into visitor(storage_.address());
1643 indicate_which(
1644 operand.internal_apply_visitor(visitor)
1645 );
1646 }
1647
1648 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1649 template <typename Variant>
convert_construct(Variant && operand,long,mpl::true_)1650 typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct(
1651 Variant&& operand
1652 , long
1653 , mpl::true_// is_foreign_variant
1654 )
1655 {
1656 convert_move_into visitor(storage_.address());
1657 indicate_which(
1658 operand.internal_apply_visitor(visitor)
1659 );
1660 }
1661 #endif
1662
1663 template <typename Variant>
convert_construct_variant(Variant & operand)1664 void convert_construct_variant(Variant& operand)
1665 {
1666 // [Determine if the given variant is itself a bounded type, or if its
1667 // content needs to be converted (i.e., it is a 'foreign' variant):]
1668 //
1669
1670 typedef typename mpl::find_if<
1671 types
1672 , is_same<
1673 add_const<mpl::_1>
1674 , const Variant
1675 >
1676 >::type found_it;
1677
1678 typedef typename mpl::end<types>::type not_found;
1679 typedef typename is_same<
1680 found_it, not_found
1681 >::type is_foreign_variant;
1682
1683 // Convert construct from operand:
1684 convert_construct(
1685 operand, 1L
1686 , is_foreign_variant()
1687 );
1688 }
1689
1690 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1691 template <typename Variant>
convert_construct_variant(Variant && operand)1692 typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct_variant(Variant&& operand)
1693 {
1694 // [Determine if the given variant is itself a bounded type, or if its
1695 // content needs to be converted (i.e., it is a 'foreign' variant):]
1696 //
1697
1698 typedef typename mpl::find_if<
1699 types
1700 , is_same<
1701 add_const<mpl::_1>
1702 , const Variant
1703 >
1704 >::type found_it;
1705
1706 typedef typename mpl::end<types>::type not_found;
1707 typedef typename is_same<
1708 found_it, not_found
1709 >::type is_foreign_variant;
1710
1711 // Convert move construct from operand:
1712 convert_construct(
1713 detail::variant::move(operand), 1L
1714 , is_foreign_variant()
1715 );
1716 }
1717 #endif
1718
1719 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1720 typename boost::enable_if<mpl::or_<
1721 boost::is_same<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>, variant>,
1722 boost::detail::variant::is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&, internal_types>
convert_construct(boost::variant<BOOST_VARIANT_ENUM_PARAMS (U)> & operand,long)1723 > >::type convert_construct(
1724 boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1725 , long
1726 )
1727 {
1728 convert_construct_variant(operand);
1729 }
1730
1731 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1732 typename boost::enable_if<mpl::or_<
1733 boost::is_same<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>, variant>,
1734 boost::detail::variant::is_variant_constructible_from<const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&, internal_types>
convert_construct(const boost::variant<BOOST_VARIANT_ENUM_PARAMS (U)> & operand,long)1735 > >::type convert_construct(
1736 const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1737 , long
1738 )
1739 {
1740 convert_construct_variant(operand);
1741 }
1742
1743 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1744 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1745 typename boost::enable_if<mpl::or_<
1746 boost::is_same<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>, variant>,
1747 boost::detail::variant::is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&&, internal_types>
convert_construct(boost::variant<BOOST_VARIANT_ENUM_PARAMS (U)> && operand,long)1748 > >::type convert_construct(
1749 boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&& operand
1750 , long
1751 )
1752 {
1753 convert_construct_variant( detail::variant::move(operand) );
1754 }
1755 #endif
1756
1757 public: // structors, cont.
1758
1759 template <typename T>
variant(const T & operand,typename boost::enable_if<mpl::or_<mpl::and_<mpl::not_<boost::is_same<T,variant>>,boost::detail::variant::is_variant_constructible_from<const T &,internal_types>>,boost::is_same<T,boost::recursive_variant_>>>::type * =0)1760 variant(const T& operand,
1761 typename boost::enable_if<mpl::or_<
1762 mpl::and_<
1763 mpl::not_< boost::is_same<T, variant> >,
1764 boost::detail::variant::is_variant_constructible_from<const T&, internal_types>
1765 >,
1766 boost::is_same<T, boost::recursive_variant_> > >::type* = 0)
1767 {
1768 convert_construct(operand, 1L);
1769 }
1770
1771 template <typename T>
variant(T & operand,typename boost::enable_if<mpl::or_<mpl::and_<mpl::not_<is_const<T>>,mpl::not_<boost::is_same<T,variant>>,boost::detail::variant::is_variant_constructible_from<T &,internal_types>>,boost::is_same<T,boost::recursive_variant_>>>::type * =0)1772 variant(
1773 T& operand
1774 , typename boost::enable_if<mpl::or_<
1775 mpl::and_<
1776 mpl::not_< is_const<T> >,
1777 mpl::not_< boost::is_same<T, variant> >,
1778 boost::detail::variant::is_variant_constructible_from<T&, internal_types>
1779 >,
1780 boost::is_same<T, boost::recursive_variant_> > >::type* = 0
1781 )
1782 {
1783 convert_construct(operand, 1L);
1784 }
1785
1786 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1787 template <class T>
variant(T && operand,typename boost::enable_if<mpl::or_<mpl::and_<boost::is_rvalue_reference<T &&>,mpl::not_<boost::is_const<T>>,mpl::not_<boost::is_same<T,variant>>,boost::detail::variant::is_variant_constructible_from<T &&,internal_types>>,boost::is_same<T,boost::recursive_variant_>>>::type * =0)1788 variant(T&& operand,
1789 typename boost::enable_if<mpl::or_<
1790 mpl::and_<
1791 boost::is_rvalue_reference<T&&>,
1792 mpl::not_< boost::is_const<T> >,
1793 mpl::not_< boost::is_same<T, variant> >,
1794 boost::detail::variant::is_variant_constructible_from<T&&, internal_types>
1795 >,
1796 boost::is_same<T, boost::recursive_variant_> > >::type* = 0)
1797 {
1798 convert_construct( detail::variant::move(operand), 1L);
1799 }
1800 #endif
1801
1802 public: // structors, cont.
1803
1804 // [MSVC6 requires copy constructor appear after template constructors]
variant(const variant & operand)1805 variant(const variant& operand)
1806 {
1807 // Copy the value of operand into *this...
1808 detail::variant::copy_into visitor( storage_.address() );
1809 operand.internal_apply_visitor(visitor);
1810
1811 // ...and activate the *this's primary storage on success:
1812 indicate_which(operand.which());
1813 }
1814
1815 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value)1816 variant(variant&& operand) BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value)
1817 {
1818 // Move the value of operand into *this...
1819 detail::variant::move_into visitor( storage_.address() );
1820 operand.internal_apply_visitor(visitor);
1821
1822 // ...and activate the *this's primary storage on success:
1823 indicate_which(operand.which());
1824 }
1825 #endif
1826
1827 private: // helpers, for modifiers (below)
1828
1829 # if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1830 template <typename Variant>
1831 friend class detail::variant::backup_assigner;
1832 # endif
1833
1834 // class assigner
1835 //
1836 // Internal visitor that "assigns" the visited value to the given variant
1837 // by appropriate destruction and copy-construction.
1838 //
1839
1840 class assigner
1841 : public static_visitor<>
1842 {
1843 protected: // representation
1844
1845 variant& lhs_;
1846 const int rhs_which_;
1847
1848 public: // structors
1849
assigner(variant & lhs,int rhs_which)1850 assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
1851 : lhs_(lhs)
1852 , rhs_which_(rhs_which)
1853 {
1854 }
1855
1856 protected: // helpers, for internal visitor interface (below)
1857
1858 template <typename RhsT, typename B1, typename B2>
assign_impl(const RhsT & rhs_content,mpl::true_,B1,B2) const1859 void assign_impl(
1860 const RhsT& rhs_content
1861 , mpl::true_ // has_nothrow_copy
1862 , B1 // is_nothrow_move_constructible
1863 , B2 // has_fallback_type
1864 ) const BOOST_NOEXCEPT
1865 {
1866 // Destroy lhs's content...
1867 lhs_.destroy_content(); // nothrow
1868
1869 // ...copy rhs content into lhs's storage...
1870 new(lhs_.storage_.address())
1871 RhsT( rhs_content ); // nothrow
1872
1873 // ...and indicate new content type:
1874 lhs_.indicate_which(rhs_which_); // nothrow
1875 }
1876
1877 template <typename RhsT, typename B>
assign_impl(const RhsT & rhs_content,mpl::false_,mpl::true_,B) const1878 void assign_impl(
1879 const RhsT& rhs_content
1880 , mpl::false_ // has_nothrow_copy
1881 , mpl::true_ // is_nothrow_move_constructible
1882 , B // has_fallback_type
1883 ) const
1884 {
1885 // Attempt to make a temporary copy (so as to move it below)...
1886 RhsT temp(rhs_content);
1887
1888 // ...and upon success destroy lhs's content...
1889 lhs_.destroy_content(); // nothrow
1890
1891 // ...move the temporary copy into lhs's storage...
1892 new(lhs_.storage_.address())
1893 RhsT( detail::variant::move(temp) ); // nothrow
1894
1895 // ...and indicate new content type:
1896 lhs_.indicate_which(rhs_which_); // nothrow
1897 }
1898
construct_fallback() const1899 void construct_fallback() const BOOST_NOEXCEPT {
1900 // In case of failure, default-construct fallback type in lhs's storage...
1901 new (lhs_.storage_.address())
1902 fallback_type_; // nothrow
1903
1904 // ...indicate construction of fallback type...
1905 lhs_.indicate_which(
1906 BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value
1907 ); // nothrow
1908 }
1909
1910 template <typename RhsT>
assign_impl(const RhsT & rhs_content,mpl::false_,mpl::false_,mpl::true_) const1911 void assign_impl(
1912 const RhsT& rhs_content
1913 , mpl::false_ // has_nothrow_copy
1914 , mpl::false_ // is_nothrow_move_constructible
1915 , mpl::true_ // has_fallback_type
1916 ) const
1917 {
1918 // Destroy lhs's content...
1919 lhs_.destroy_content(); // nothrow
1920
1921 BOOST_TRY
1922 {
1923 // ...and attempt to copy rhs's content into lhs's storage:
1924 new(lhs_.storage_.address())
1925 RhsT( rhs_content );
1926 }
1927 BOOST_CATCH (...)
1928 {
1929 construct_fallback();
1930
1931 // ...and rethrow:
1932 BOOST_RETHROW;
1933 }
1934 BOOST_CATCH_END
1935
1936 // In the event of success, indicate new content type:
1937 lhs_.indicate_which(rhs_which_); // nothrow
1938 }
1939
1940 template <typename RhsT>
assign_impl(const RhsT & rhs_content,mpl::false_,mpl::false_,mpl::false_) const1941 void assign_impl(
1942 const RhsT& rhs_content
1943 , mpl::false_ // has_nothrow_copy
1944 , mpl::false_ // is_nothrow_move_constructible
1945 , mpl::false_ // has_fallback_type
1946 ) const
1947 {
1948 detail::variant::backup_assigner<wknd_self_t>
1949 visitor(lhs_, rhs_which_, rhs_content);
1950 lhs_.internal_apply_visitor(visitor);
1951 }
1952
1953 public: // internal visitor interfaces
1954
1955 template <typename RhsT>
1956 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visit(const RhsT & rhs_content,int) const1957 internal_visit(const RhsT& rhs_content, int) const
1958 {
1959 typedef typename has_nothrow_copy<RhsT>::type
1960 nothrow_copy;
1961 typedef typename mpl::or_< // reduces compile-time
1962 nothrow_copy
1963 , is_nothrow_move_constructible<RhsT>
1964 >::type nothrow_move_constructor;
1965
1966 assign_impl(
1967 rhs_content
1968 , nothrow_copy()
1969 , nothrow_move_constructor()
1970 , has_fallback_type_()
1971 );
1972
1973 BOOST_VARIANT_AUX_RETURN_VOID;
1974 }
1975
1976 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
1977 private:
1978 // silence MSVC warning C4512: assignment operator could not be generated
1979 assigner& operator= (assigner const&);
1980 #endif
1981 };
1982
1983 friend class assigner;
1984
1985 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1986 // class move_assigner
1987 //
1988 // Internal visitor that "move assigns" the visited value to the given variant
1989 // by appropriate destruction and move-construction.
1990 //
1991
1992 class move_assigner
1993 : public assigner
1994 {
1995 public: // structors
1996
move_assigner(variant & lhs,int rhs_which)1997 move_assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
1998 : assigner(lhs, rhs_which)
1999 {
2000 }
2001
2002 private: // helpers, for internal visitor interface (below)
2003
2004 template <typename RhsT, typename B2>
assign_impl(RhsT & rhs_content,mpl::true_,mpl::false_,B2) const2005 void assign_impl(
2006 RhsT& rhs_content
2007 , mpl::true_ // has_nothrow_copy
2008 , mpl::false_ // is_nothrow_move_constructible
2009 , B2 // has_fallback_type
2010 ) const BOOST_NOEXCEPT
2011 {
2012 assigner::assign_impl(rhs_content, mpl::true_(), mpl::false_(), B2());
2013 }
2014
2015 template <typename RhsT, typename B, typename B2>
assign_impl(RhsT & rhs_content,B,mpl::true_,B2) const2016 void assign_impl(
2017 RhsT& rhs_content
2018 , B // has_nothrow_copy
2019 , mpl::true_ // is_nothrow_move_constructible
2020 , B2 // has_fallback_type
2021 ) const BOOST_NOEXCEPT
2022 {
2023 // ...destroy lhs's content...
2024 assigner::lhs_.destroy_content(); // nothrow
2025
2026 // ...move the rhs_content into lhs's storage...
2027 new(assigner::lhs_.storage_.address())
2028 RhsT( detail::variant::move(rhs_content) ); // nothrow
2029
2030 // ...and indicate new content type:
2031 assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
2032 }
2033
2034 template <typename RhsT>
assign_impl(RhsT & rhs_content,mpl::false_,mpl::false_,mpl::true_) const2035 void assign_impl(
2036 RhsT& rhs_content
2037 , mpl::false_ // has_nothrow_copy
2038 , mpl::false_ // is_nothrow_move_constructible
2039 , mpl::true_ // has_fallback_type
2040 ) const
2041 {
2042 // Destroy lhs's content...
2043 assigner::lhs_.destroy_content(); // nothrow
2044
2045 BOOST_TRY
2046 {
2047 // ...and attempt to copy rhs's content into lhs's storage:
2048 new(assigner::lhs_.storage_.address())
2049 RhsT( detail::variant::move(rhs_content) );
2050 }
2051 BOOST_CATCH (...)
2052 {
2053 assigner::construct_fallback();
2054
2055 // ...and rethrow:
2056 BOOST_RETHROW;
2057 }
2058 BOOST_CATCH_END
2059
2060 // In the event of success, indicate new content type:
2061 assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
2062 }
2063
2064 template <typename RhsT>
assign_impl(RhsT & rhs_content,mpl::false_,mpl::false_,mpl::false_) const2065 void assign_impl(
2066 RhsT& rhs_content
2067 , mpl::false_ // has_nothrow_copy
2068 , mpl::false_ // is_nothrow_move_constructible
2069 , mpl::false_ // has_fallback_type
2070 ) const
2071 {
2072 assigner::assign_impl(rhs_content, mpl::false_(), mpl::false_(), mpl::false_());
2073 }
2074
2075 public: // internal visitor interfaces
2076
2077 template <typename RhsT>
2078 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
internal_visit(RhsT & rhs_content,int) const2079 internal_visit(RhsT& rhs_content, int) const
2080 {
2081 typedef typename is_nothrow_move_constructible<RhsT>::type
2082 nothrow_move_constructor;
2083 typedef typename mpl::or_< // reduces compile-time
2084 nothrow_move_constructor
2085 , has_nothrow_copy<RhsT>
2086 >::type nothrow_copy;
2087
2088 assign_impl(
2089 rhs_content
2090 , nothrow_copy()
2091 , nothrow_move_constructor()
2092 , has_fallback_type_()
2093 );
2094
2095 BOOST_VARIANT_AUX_RETURN_VOID;
2096 }
2097
2098 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
2099 private:
2100 // silence MSVC warning C4512: assignment operator could not be generated
2101 move_assigner& operator= (move_assigner const&);
2102 #endif
2103 };
2104
2105 friend class move_assigner;
2106 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2107
variant_assign(const variant & rhs)2108 void variant_assign(const variant& rhs)
2109 {
2110 // If the contained types are EXACTLY the same...
2111 if (which_ == rhs.which_)
2112 {
2113 // ...then assign rhs's storage to lhs's content:
2114 detail::variant::assign_storage visitor(rhs.storage_.address());
2115 this->internal_apply_visitor(visitor);
2116 }
2117 else
2118 {
2119 // Otherwise, perform general (copy-based) variant assignment:
2120 assigner visitor(*this, rhs.which());
2121 rhs.internal_apply_visitor(visitor);
2122 }
2123 }
2124
2125 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
variant_assign(variant && rhs)2126 void variant_assign(variant&& rhs)
2127 {
2128 // If the contained types are EXACTLY the same...
2129 if (which_ == rhs.which_)
2130 {
2131 // ...then move rhs's storage to lhs's content:
2132 detail::variant::move_storage visitor(rhs.storage_.address());
2133 this->internal_apply_visitor(visitor);
2134 }
2135 else
2136 {
2137 // Otherwise, perform general (move-based) variant assignment:
2138 move_assigner visitor(*this, rhs.which());
2139 rhs.internal_apply_visitor(visitor);
2140 }
2141 }
2142 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2143
2144 private: // helpers, for modifiers (below)
2145
2146 template <typename T>
assign(const T & rhs)2147 void assign(const T& rhs)
2148 {
2149 // If direct T-to-T assignment is not possible...
2150 detail::variant::direct_assigner<T> direct_assign(rhs);
2151 if (this->apply_visitor(direct_assign) == false)
2152 {
2153 // ...then convert rhs to variant and assign:
2154 //
2155 // While potentially inefficient, the following construction of a
2156 // variant allows T as any type convertible to one of the bounded
2157 // types without excessive code redundancy.
2158 //
2159 variant temp(rhs);
2160 variant_assign( detail::variant::move(temp) );
2161 }
2162 }
2163
2164 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2165 template <typename T>
move_assign(T && rhs)2166 void move_assign(T&& rhs)
2167 {
2168 // If direct T-to-T move assignment is not possible...
2169 detail::variant::direct_mover<T> direct_move(rhs);
2170 if (this->apply_visitor(direct_move) == false)
2171 {
2172 // ...then convert rhs to variant and assign:
2173 //
2174 // While potentially inefficient, the following construction of a
2175 // variant allows T as any type convertible to one of the bounded
2176 // types without excessive code redundancy.
2177 //
2178 variant temp( detail::variant::move(rhs) );
2179 variant_assign( detail::variant::move(temp) );
2180 }
2181 }
2182 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2183
2184 public: // modifiers
2185
2186 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2187 template <class T>
2188 typename boost::enable_if<
2189 boost::mpl::and_<
2190 boost::is_rvalue_reference<T&&>,
2191 mpl::not_< boost::is_const<T> >,
2192 boost::detail::variant::is_variant_constructible_from<T&&, internal_types>
2193 >,
2194 variant&
operator =(T && rhs)2195 >::type operator=(T&& rhs)
2196 {
2197 move_assign( detail::variant::move(rhs) );
2198 return *this;
2199 }
2200 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2201
2202 template <typename T>
2203 typename boost::enable_if<
2204 mpl::or_<
2205 boost::is_same<T, variant>,
2206 boost::detail::variant::is_variant_constructible_from<const T&, internal_types>
2207 >,
2208 variant&
operator =(const T & rhs)2209 >::type operator=(const T& rhs)
2210 {
2211 assign(rhs);
2212 return *this;
2213 }
2214
2215 // [MSVC6 requires copy assign appear after templated operator=]
operator =(const variant & rhs)2216 variant& operator=(const variant& rhs)
2217 {
2218 variant_assign(rhs);
2219 return *this;
2220 }
2221
2222 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
operator =(variant && rhs)2223 variant& operator=(variant&& rhs)
2224 #if !defined(__GNUC__) || (__GNUC__ != 4) || (__GNUC_MINOR__ > 6) || defined(__clang__)
2225 BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value && variant_move_noexcept_assignable::type::value)
2226 #endif
2227 {
2228 variant_assign( detail::variant::move(rhs) );
2229 return *this;
2230 }
2231 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2232
swap(variant & rhs)2233 void swap(variant& rhs)
2234 {
2235 // If the contained types are the same...
2236 if (which() == rhs.which())
2237 {
2238 // ...then swap the values directly:
2239 detail::variant::swap_with<variant> visitor(rhs);
2240 this->apply_visitor(visitor);
2241 }
2242 else
2243 {
2244 // ...otherwise, perform general variant swap:
2245 variant tmp( detail::variant::move(rhs) );
2246 rhs = detail::variant::move(*this);
2247 *this = detail::variant::move(tmp);
2248 }
2249 }
2250
2251 public: // queries
2252
2253 //
2254 // NOTE: member which() defined above.
2255 //
2256
empty() const2257 bool empty() const BOOST_NOEXCEPT
2258 {
2259 return false;
2260 }
2261
type() const2262 const boost::typeindex::type_info& type() const
2263 {
2264 detail::variant::reflect visitor;
2265 return this->apply_visitor(visitor);
2266 }
2267
2268 public: // prevent comparison with foreign types
2269
2270 template <typename U>
operator ==(const U &) const2271 void operator==(const U&) const
2272 {
2273 BOOST_STATIC_ASSERT( false && sizeof(U) );
2274 }
2275
2276 template <typename U>
operator <(const U &) const2277 void operator<(const U&) const
2278 {
2279 BOOST_STATIC_ASSERT( false && sizeof(U) );
2280 }
2281
2282 template <typename U>
operator !=(const U &) const2283 void operator!=(const U&) const
2284 {
2285 BOOST_STATIC_ASSERT( false && sizeof(U) );
2286 }
2287
2288 template <typename U>
operator >(const U &) const2289 void operator>(const U&) const
2290 {
2291 BOOST_STATIC_ASSERT( false && sizeof(U) );
2292 }
2293
2294 template <typename U>
operator <=(const U &) const2295 void operator<=(const U&) const
2296 {
2297 BOOST_STATIC_ASSERT( false && sizeof(U) );
2298 }
2299
2300 template <typename U>
operator >=(const U &) const2301 void operator>=(const U&) const
2302 {
2303 BOOST_STATIC_ASSERT( false && sizeof(U) );
2304 }
2305
2306 public: // comparison operators
2307
2308 // [MSVC6 requires these operators appear after template operators]
2309
operator ==(const variant & rhs) const2310 bool operator==(const variant& rhs) const
2311 {
2312 if (this->which() != rhs.which())
2313 return false;
2314
2315 detail::variant::comparer<
2316 variant, detail::variant::equal_comp
2317 > visitor(*this);
2318 return rhs.apply_visitor(visitor);
2319 }
2320
operator <(const variant & rhs) const2321 bool operator<(const variant& rhs) const
2322 {
2323 //
2324 // Dirk Schreib suggested this collating order.
2325 //
2326
2327 if (this->which() != rhs.which())
2328 return this->which() < rhs.which();
2329
2330 detail::variant::comparer<
2331 variant, detail::variant::less_comp
2332 > visitor(*this);
2333 return rhs.apply_visitor(visitor);
2334 }
2335
2336 ///////////////////////////////////////////////////////////////////////////////
2337 // comparison operators != > <= >=
operator !=(const variant & rhs) const2338 inline bool operator!=(const variant& rhs) const
2339 {
2340 return !(*this == rhs);
2341 }
2342
operator >(const variant & rhs) const2343 inline bool operator>(const variant& rhs) const
2344 {
2345 return rhs < *this;
2346 }
2347
operator <=(const variant & rhs) const2348 inline bool operator<=(const variant& rhs) const
2349 {
2350 return !(*this > rhs);
2351 }
2352
operator >=(const variant & rhs) const2353 inline bool operator>=(const variant& rhs) const
2354 {
2355 return !(*this < rhs);
2356 }
2357
2358 // helpers, for visitation support (below) -- private when possible
2359 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2360
2361 template < BOOST_VARIANT_ENUM_PARAMS(typename U) >
2362 friend class variant;
2363
2364 private:
2365
2366 #else// defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2367
2368 public:
2369
2370 #endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2371
2372 template <typename Visitor, typename VoidPtrCV>
2373 static
2374 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2375 typename Visitor::result_type
2376 )
internal_apply_visitor_impl(int internal_which,int logical_which,Visitor & visitor,VoidPtrCV storage)2377 internal_apply_visitor_impl(
2378 int internal_which
2379 , int logical_which
2380 , Visitor& visitor
2381 , VoidPtrCV storage
2382 )
2383 {
2384 typedef mpl::int_<0> first_which;
2385 typedef typename mpl::begin<internal_types>::type first_it;
2386 typedef typename mpl::end<internal_types>::type last_it;
2387
2388 typedef detail::variant::visitation_impl_step<
2389 first_it, last_it
2390 > first_step;
2391
2392 return detail::variant::visitation_impl(
2393 internal_which, logical_which
2394 , visitor, storage, mpl::false_()
2395 , never_uses_backup_flag()
2396 , static_cast<first_which*>(0), static_cast<first_step*>(0)
2397 );
2398 }
2399
2400 template <typename Visitor>
2401 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2402 typename Visitor::result_type
2403 )
internal_apply_visitor(Visitor & visitor)2404 internal_apply_visitor(Visitor& visitor)
2405 {
2406 return internal_apply_visitor_impl(
2407 which_, which(), visitor, storage_.address()
2408 );
2409 }
2410
2411 template <typename Visitor>
2412 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2413 typename Visitor::result_type
2414 )
internal_apply_visitor(Visitor & visitor) const2415 internal_apply_visitor(Visitor& visitor) const
2416 {
2417 return internal_apply_visitor_impl(
2418 which_, which(), visitor, storage_.address()
2419 );
2420 }
2421
2422 public: // visitation support
2423
2424 template <typename Visitor>
2425 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2426 typename Visitor::result_type
2427 )
apply_visitor(Visitor & visitor)2428 apply_visitor(Visitor& visitor)
2429 {
2430 detail::variant::invoke_visitor<Visitor> invoker(visitor);
2431 return this->internal_apply_visitor(invoker);
2432 }
2433
2434 template <typename Visitor>
2435 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2436 typename Visitor::result_type
2437 )
apply_visitor(Visitor & visitor) const2438 apply_visitor(Visitor& visitor) const
2439 {
2440 detail::variant::invoke_visitor<Visitor> invoker(visitor);
2441 return this->internal_apply_visitor(invoker);
2442 }
2443
2444 }; // class variant
2445
2446 ///////////////////////////////////////////////////////////////////////////////
2447 // metafunction make_variant_over
2448 //
2449 // See docs and boost/variant/variant_fwd.hpp for more information.
2450 //
2451 template <typename Types>
2452 struct make_variant_over
2453 {
2454 private: // precondition assertions
2455
2456 BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value ));
2457 typedef typename boost::mpl::insert_range<
2458 boost::mpl::list<>
2459 , boost::mpl::end< boost::mpl::list<> >::type
2460 , Types
2461 >::type copied_sequence_t;
2462
2463 public: // metafunction result
2464
2465 typedef variant<
2466 detail::variant::over_sequence<copied_sequence_t>
2467 > type;
2468
2469 };
2470
2471 ///////////////////////////////////////////////////////////////////////////////
2472 // function template swap
2473 //
2474 // Swaps two variants of the same type (i.e., identical specification).
2475 //
2476 template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
swap(variant<BOOST_VARIANT_ENUM_PARAMS (T)> & lhs,variant<BOOST_VARIANT_ENUM_PARAMS (T)> & rhs)2477 inline void swap(
2478 variant< BOOST_VARIANT_ENUM_PARAMS(T) >& lhs
2479 , variant< BOOST_VARIANT_ENUM_PARAMS(T) >& rhs
2480 )
2481 {
2482 lhs.swap(rhs);
2483 }
2484
2485 } // namespace boost
2486
2487 // implementation additions
2488
2489 #if !defined(BOOST_NO_IOSTREAM)
2490 #include <boost/variant/detail/variant_io.hpp>
2491 #endif // BOOST_NO_IOSTREAM
2492
2493 #endif // BOOST_VARIANT_VARIANT_HPP
2494