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-2021 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 #include <boost/variant/detail/std_hash.hpp>
36 
37 #include <boost/variant/detail/move.hpp>
38 
39 #include <boost/detail/reference_content.hpp>
40 #include <boost/blank.hpp>
41 #include <boost/integer/common_factor_ct.hpp>
42 #include <boost/static_assert.hpp>
43 #include <boost/preprocessor/cat.hpp>
44 #include <boost/preprocessor/repeat.hpp>
45 #include <boost/type_traits/aligned_storage.hpp>
46 #include <boost/type_traits/alignment_of.hpp>
47 #include <boost/type_traits/add_const.hpp>
48 #include <boost/type_traits/has_nothrow_constructor.hpp>
49 #include <boost/type_traits/has_nothrow_copy.hpp>
50 #include <boost/type_traits/is_nothrow_move_assignable.hpp>
51 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
52 #include <boost/type_traits/is_const.hpp>
53 #include <boost/type_traits/is_same.hpp>
54 #include <boost/type_traits/is_rvalue_reference.hpp>
55 #include <boost/type_traits/is_constructible.hpp>
56 #include <boost/type_traits/add_lvalue_reference.hpp>
57 #include <boost/type_traits/declval.hpp>
58 #include <boost/core/no_exceptions_support.hpp>
59 #include <boost/core/enable_if.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::integer::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(BOOST_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>
internal_visitboost::detail::variant::destroyer384     void internal_visit(T& operand, int) const BOOST_NOEXCEPT
385     {
386         operand.~T(); // must be noexcept
387 
388 #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0551)) || \
389     BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
390         (void)operand; // suppresses warnings
391 #endif
392     }
393 
394 };
395 
396 ///////////////////////////////////////////////////////////////////////////////
397 // (detail) class template known_get
398 //
399 // Visitor that returns a reference to content of the specified type.
400 //
401 // Precondition: visited variant MUST contain logical content of type T.
402 //
403 template <typename T>
404 class known_get
405     : public static_visitor<T&>
406 {
407 
408 public: // visitor interface
409 
operator ()(T & operand) const410     T& operator()(T& operand) const BOOST_NOEXCEPT
411     {
412         return operand;
413     }
414 
415     template <typename U>
operator ()(U &) const416     T& operator()(U&) const
417     {
418         // logical error to be here: see precondition above
419         return ::boost::detail::variant::forced_return< T& >();
420     }
421 };
422 
423 ///////////////////////////////////////////////////////////////////////////////
424 // (detail) class copy_into
425 //
426 // Internal visitor that copies the value it visits into the given buffer.
427 //
428 class copy_into
429     : public static_visitor<>
430 {
431 private: // representation
432 
433     void* storage_;
434 
435 public: // structors
436 
copy_into(void * storage)437     explicit copy_into(void* storage) BOOST_NOEXCEPT
438         : storage_(storage)
439     {
440     }
441 
442 public: // internal visitor interface
443 
444     template <typename T>
internal_visit(boost::detail::variant::backup_holder<T> & operand,long) const445     void internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
446     {
447         new(storage_) T( operand.get() );
448     }
449 
450     template <typename T>
internal_visit(const boost::detail::variant::backup_holder<T> & operand,long) const451     void internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
452     {
453         new(storage_) T( operand.get() );
454     }
455 
456     template <typename T>
internal_visit(const T & operand,int) const457     void internal_visit(const T& operand, int) const
458     {
459         new(storage_) T(operand);
460     }
461 
462 };
463 
464 ///////////////////////////////////////////////////////////////////////////////
465 // (detail) class move_into
466 //
467 // Internal visitor that moves the value it visits into the given buffer.
468 //
469 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
470 class move_into
471     : public static_visitor<>
472 {
473 private: // representation
474 
475     void* storage_;
476 
477 public: // structors
478 
move_into(void * storage)479     explicit move_into(void* storage) BOOST_NOEXCEPT
480         : storage_(storage)
481     {
482     }
483 
484 public: // internal visitor interface
485 
486     template <typename T>
internal_visit(boost::detail::variant::backup_holder<T> & operand,long) const487     void internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
488     {
489         new(storage_) T( ::boost::detail::variant::move(operand.get()) );
490     }
491 
492     template <typename T>
internal_visit(T & operand,int) const493     void internal_visit(T& operand, int) const BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(boost::declval<T>())))
494     {
495         new(storage_) T(::boost::detail::variant::move(operand));
496     }
497 };
498 #endif
499 
500 ///////////////////////////////////////////////////////////////////////////////
501 // (detail) class assign_storage
502 //
503 // Internal visitor that assigns the given storage (which must be a
504 // constructed value of the same type) to the value it visits.
505 //
506 struct assign_storage
507     : public static_visitor<>
508 {
509 private: // representation
510 
511     const void* rhs_storage_;
512 
513 public: // structors
514 
assign_storageboost::detail::variant::assign_storage515     explicit assign_storage(const void* rhs_storage) BOOST_NOEXCEPT
516         : rhs_storage_(rhs_storage)
517     {
518     }
519 
520 public: // internal visitor interfaces
521 
522     template <typename T>
internal_visitboost::detail::variant::assign_storage523     void internal_visit(backup_holder<T>& lhs_content, long) const
524     {
525         lhs_content.get()
526             = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
527     }
528 
529     template <typename T>
internal_visitboost::detail::variant::assign_storage530     void internal_visit(const backup_holder<T>& lhs_content, long) const
531     {
532         lhs_content.get()
533             = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
534     }
535 
536     template <typename T>
internal_visitboost::detail::variant::assign_storage537     void internal_visit(T& lhs_content, int) const
538     {
539         // NOTE TO USER :
540         // Compile error here indicates one of variant's bounded types does
541         // not meet the requirements of the Assignable concept. Thus,
542         // variant is not Assignable.
543         //
544         // Hint: Are any of the bounded types const-qualified or references?
545         //
546         lhs_content = *static_cast< const T* >(rhs_storage_);
547     }
548 
549 };
550 
551 ///////////////////////////////////////////////////////////////////////////////
552 // (detail) class move_storage
553 //
554 // Internal visitor that moves the given storage (which must be a
555 // constructed value of the same type) to the value it visits.
556 //
557 struct move_storage
558     : public static_visitor<>
559 {
560 private: // representation
561 
562     void* rhs_storage_;
563 
564 public: // structors
565 
move_storageboost::detail::variant::move_storage566     explicit move_storage(void* rhs_storage) BOOST_NOEXCEPT
567         : rhs_storage_(rhs_storage)
568     {
569     }
570 
571 public: // internal visitor interfaces
572 
573     template <typename T>
internal_visitboost::detail::variant::move_storage574     void internal_visit(backup_holder<T>& lhs_content, long) const
575     {
576         lhs_content.get()
577             = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
578     }
579 
580     template <typename T>
internal_visitboost::detail::variant::move_storage581     void internal_visit(const backup_holder<T>& lhs_content, long) const
582     {
583         lhs_content.get()
584             = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
585     }
586 
587     template <typename T>
internal_visitboost::detail::variant::move_storage588     void internal_visit(T& lhs_content, int) const
589     {
590         // NOTE TO USER :
591         // Compile error here indicates one of variant's bounded types does
592         // not meet the requirements of the Assignable concept. Thus,
593         // variant is not Assignable.
594         //
595         // Hint: Are any of the bounded types const-qualified or references?
596         //
597         lhs_content = ::boost::detail::variant::move(*static_cast<T* >(rhs_storage_));
598     }
599 
600 };
601 
602 ///////////////////////////////////////////////////////////////////////////////
603 // (detail) class direct_assigner
604 //
605 // Generic static visitor that: if and only if the visited value is of the
606 // specified type, assigns the given value to the visited value and returns
607 // true; else returns false.
608 //
609 template <typename T>
610 class direct_assigner
611     : public static_visitor<bool>
612 {
613 private: // representation
614 
615     const T& rhs_;
616 
617 public: // structors
618 
direct_assigner(const T & rhs)619     explicit direct_assigner(const T& rhs) BOOST_NOEXCEPT
620         : rhs_(rhs)
621     {
622     }
623 
624 public: // visitor interface
625 
operator ()(T & lhs)626     bool operator()(T& lhs)
627     {
628         lhs = rhs_;
629         return true;
630     }
631 
632     template <typename U>
operator ()(U &)633     bool operator()(U&) BOOST_NOEXCEPT
634     {
635         return false;
636     }
637 
638 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
639 private:
640     // silence MSVC warning C4512: assignment operator could not be generated
641     direct_assigner& operator= (direct_assigner const&);
642 #endif
643 };
644 
645 ///////////////////////////////////////////////////////////////////////////////
646 // (detail) class direct_mover
647 //
648 // Generic static visitor that: if and only if the visited value is of the
649 // specified type, move assigns the given value to the visited value and returns
650 // true; else returns false.
651 //
652 template <typename T>
653 class direct_mover
654     : public static_visitor<bool>
655 {
656 private: // representation
657 
658     T& rhs_;
659 
660 public: // structors
661 
direct_mover(T & rhs)662     explicit direct_mover(T& rhs) BOOST_NOEXCEPT
663         : rhs_(rhs)
664     {
665     }
666 
667 public: // visitor interface
668 
operator ()(T & lhs)669     bool operator()(T& lhs)
670     {
671         lhs = ::boost::detail::variant::move(rhs_);
672         return true;
673     }
674 
675     template <typename U>
operator ()(U &)676     bool operator()(U&) BOOST_NOEXCEPT
677     {
678         return false;
679     }
680 
681 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
682 private:
683     // silence MSVC warning C4512: assignment operator could not be generated
684     direct_mover& operator= (direct_mover const&);
685 #endif
686 };
687 
688 
689 ///////////////////////////////////////////////////////////////////////////////
690 // (detail) class backup_assigner
691 //
692 // Internal visitor that "assigns" the given value to the visited value,
693 // using backup to recover if the destroy-copy sequence fails.
694 //
695 // NOTE: This needs to be a friend of variant, as it needs access to
696 // indicate_which, indicate_backup_which, etc.
697 //
698 template <typename Variant>
699 class backup_assigner
700     : public static_visitor<>
701 {
702 private: // representation
703 
704     Variant& lhs_;
705     int rhs_which_;
706     const void* rhs_content_;
707     void (*copy_rhs_content_)(void*, const void*);
708 
709 public: // structors
710 
711     template<class RhsT>
backup_assigner(Variant & lhs,int rhs_which,const RhsT & rhs_content)712     backup_assigner(Variant& lhs, int rhs_which, const RhsT& rhs_content)
713         : lhs_(lhs)
714         , rhs_which_(rhs_which)
715         , rhs_content_(&rhs_content)
716         , copy_rhs_content_(&construct_impl<RhsT>)
717     {
718     }
719 
720 private: // helpers, for visitor interface (below)
721 
722     template<class RhsT>
construct_impl(void * addr,const void * obj)723     static void construct_impl(void* addr, const void* obj)
724     {
725         new(addr) RhsT(*static_cast<const RhsT*>(obj));
726     }
727 
728     template <typename LhsT>
backup_assign_impl(backup_holder<LhsT> & lhs_content,mpl::false_,long)729     void backup_assign_impl(
730           backup_holder<LhsT>& lhs_content
731         , mpl::false_ // is_nothrow_move_constructible
732         , long
733         )
734     {
735         // Move lhs content to backup...
736         backup_holder<LhsT> backup_lhs_content(0);
737         backup_lhs_content.swap(lhs_content); // nothrow
738 
739         // ...destroy lhs content...
740         lhs_content.~backup_holder<LhsT>(); // nothrow
741 
742         BOOST_TRY
743         {
744             // ...and attempt to copy rhs content into lhs storage:
745             copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
746         }
747         BOOST_CATCH (...)
748         {
749             // In case of failure, copy backup pointer to lhs storage...
750             new(lhs_.storage_.address())
751                     backup_holder<LhsT>( 0 ); // nothrow
752 
753             static_cast<backup_holder<LhsT>* >(lhs_.storage_.address())
754                     ->swap(backup_lhs_content); // nothrow
755 
756             // ...and rethrow:
757             BOOST_RETHROW;
758         }
759         BOOST_CATCH_END
760 
761         // In case of success, indicate new content type:
762         lhs_.indicate_which(rhs_which_); // nothrow
763     }
764 
765     template <typename LhsT>
backup_assign_impl(LhsT & lhs_content,mpl::true_,int)766     void backup_assign_impl(
767           LhsT& lhs_content
768         , mpl::true_ // is_nothrow_move_constructible
769         , int
770         )
771     {
772         // Move lhs content to backup...
773         LhsT backup_lhs_content(
774               ::boost::detail::variant::move(lhs_content)
775             ); // nothrow
776 
777         // ...destroy lhs content...
778         lhs_content.~LhsT(); // nothrow
779 
780         BOOST_TRY
781         {
782             // ...and attempt to copy rhs content into lhs storage:
783             copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
784         }
785         BOOST_CATCH (...)
786         {
787             // In case of failure, restore backup content to lhs storage...
788             new(lhs_.storage_.address())
789                 LhsT(
790                       ::boost::detail::variant::move(backup_lhs_content)
791                     ); // nothrow
792 
793             // ...and rethrow:
794             BOOST_RETHROW;
795         }
796         BOOST_CATCH_END
797 
798         // In case of success, indicate new content type:
799         lhs_.indicate_which(rhs_which_); // nothrow
800     }
801 
802     template <typename LhsT>
backup_assign_impl(LhsT & lhs_content,mpl::false_,int)803     void backup_assign_impl(
804           LhsT& lhs_content
805         , mpl::false_ // is_nothrow_move_constructible
806         , int
807         )
808     {
809         // Backup lhs content...
810         LhsT* backup_lhs_ptr = new LhsT(lhs_content);
811 
812         // ...destroy lhs content...
813         lhs_content.~LhsT(); // nothrow
814 
815         BOOST_TRY
816         {
817             // ...and attempt to copy rhs content into lhs storage:
818             copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
819         }
820         BOOST_CATCH (...)
821         {
822             // In case of failure, copy backup pointer to lhs storage...
823             new(lhs_.storage_.address())
824                 backup_holder<LhsT>( backup_lhs_ptr ); // nothrow
825 
826             // ...indicate now using backup...
827             lhs_.indicate_backup_which( lhs_.which() ); // nothrow
828 
829             // ...and rethrow:
830             BOOST_RETHROW;
831         }
832         BOOST_CATCH_END
833 
834         // In case of success, indicate new content type...
835         lhs_.indicate_which(rhs_which_); // nothrow
836 
837         // ...and delete backup:
838         delete backup_lhs_ptr; // nothrow
839     }
840 
841 public: // visitor interface
842 
843     template <typename LhsT>
internal_visit(LhsT & lhs_content,int)844     void internal_visit(LhsT& lhs_content, int)
845     {
846         typedef typename is_nothrow_move_constructible<LhsT>::type
847             nothrow_move;
848 
849         backup_assign_impl( lhs_content, nothrow_move(), 1L);
850     }
851 
852 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
853 private:
854     // silence MSVC warning C4512: assignment operator could not be generated
855     backup_assigner& operator= (backup_assigner const&);
856 #endif
857 };
858 
859 ///////////////////////////////////////////////////////////////////////////////
860 // (detail) class swap_with
861 //
862 // Visitor that swaps visited value with content of given variant.
863 //
864 // Precondition: Given variant MUST have same logical type as visited value.
865 //
866 template <typename Variant>
867 struct swap_with
868     : public static_visitor<>
869 {
870 private: // representation
871 
872     Variant& toswap_;
873 
874 public: // structors
875 
swap_withboost::detail::variant::swap_with876     explicit swap_with(Variant& toswap) BOOST_NOEXCEPT
877         : toswap_(toswap)
878     {
879     }
880 
881 public: // internal visitor interfaces
882 
883     template <typename T>
operator ()boost::detail::variant::swap_with884     void operator()(T& operand) const
885     {
886         // Since the precondition ensures types are same, get T...
887         known_get<T> getter;
888         T& other = toswap_.apply_visitor(getter);
889 
890         // ...and swap:
891         ::boost::detail::variant::move_swap( operand, other );
892     }
893 
894 private:
895     swap_with& operator=(const swap_with&);
896 
897 };
898 
899 ///////////////////////////////////////////////////////////////////////////////
900 // (detail) class reflect
901 //
902 // Generic static visitor that performs a typeid on the value it visits.
903 //
904 
905 class reflect
906     : public static_visitor<const boost::typeindex::type_info&>
907 {
908 public: // visitor interfaces
909 
910     template <typename T>
operator ()(const T &) const911     const boost::typeindex::type_info& operator()(const T&) const BOOST_NOEXCEPT
912     {
913         return boost::typeindex::type_id<T>().type_info();
914     }
915 
916 };
917 
918 ///////////////////////////////////////////////////////////////////////////////
919 // (detail) class comparer
920 //
921 // Generic static visitor that compares the content of the given lhs variant
922 // with the visited rhs content using Comp.
923 //
924 // Precondition: lhs.which() == rhs.which()
925 //
926 template <typename Variant, typename Comp>
927 class comparer
928     : public static_visitor<bool>
929 {
930 private: // representation
931 
932     const Variant& lhs_;
933 
934 public: // structors
935 
comparer(const Variant & lhs)936     explicit comparer(const Variant& lhs) BOOST_NOEXCEPT
937         : lhs_(lhs)
938     {
939     }
940 
941 public: // visitor interfaces
942 
943     template <typename T>
operator ()(T & rhs_content) const944     bool operator()(T& rhs_content) const
945     {
946         // Since the precondition ensures lhs and rhs types are same, get T...
947         known_get<T> getter;
948         const T& lhs_content = lhs_.apply_visitor(getter);
949 
950         // ...and compare lhs and rhs contents:
951         return Comp()(lhs_content, rhs_content);
952     }
953 
954 private:
955     comparer& operator=(const comparer&);
956 
957 };
958 
959 ///////////////////////////////////////////////////////////////////////////////
960 // (detail) class equal_comp
961 //
962 // Generic function object compares lhs with rhs using operator==.
963 //
964 struct equal_comp
965 {
966     template <typename T>
operator ()boost::detail::variant::equal_comp967     bool operator()(const T& lhs, const T& rhs) const
968     {
969         return lhs == rhs;
970     }
971 };
972 
973 ///////////////////////////////////////////////////////////////////////////////
974 // (detail) class less_comp
975 //
976 // Generic function object compares lhs with rhs using operator<.
977 //
978 struct less_comp
979 {
980     template <typename T>
operator ()boost::detail::variant::less_comp981     bool operator()(const T& lhs, const T& rhs) const
982     {
983         return lhs < rhs;
984     }
985 };
986 
987 ///////////////////////////////////////////////////////////////////////////////
988 // (detail) class template invoke_visitor
989 //
990 // Internal visitor that invokes the given visitor using:
991 //  * for wrappers (e.g., recursive_wrapper), the wrapper's held value.
992 //  * for all other values, the value itself.
993 //
994 template <typename Visitor, bool MoveSemantics>
995 class invoke_visitor
996 {
997 private: // representation
998 
999     Visitor& visitor_;
1000 
1001 public: // visitor typedefs
1002 
1003     typedef typename Visitor::result_type
1004         result_type;
1005 
1006 public: // structors
1007 
invoke_visitor(Visitor & visitor)1008     explicit invoke_visitor(Visitor& visitor) BOOST_NOEXCEPT
1009         : visitor_(visitor)
1010     {
1011     }
1012 
1013 public: // internal visitor interfaces
1014 
1015 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1016 
1017     //using workaround with is_same<T, T> to prenvent compilation error, because we need to use T in enable_if to make SFINAE work
1018     template <typename T>
internal_visit(T && operand,int)1019     typename enable_if_c<MoveSemantics && is_same<T, T>::value, result_type>::type internal_visit(T&& operand, int)
1020     {
1021         return visitor_(::boost::move(operand));
1022     }
1023 
1024     //using workaround with is_same<T, T> to prenvent compilation error, because we need to use T in enable_if to make SFINAE work
1025     template <typename T>
internal_visit(T && operand,int)1026     typename disable_if_c<MoveSemantics && is_same<T, T>::value, result_type>::type internal_visit(T&& operand, int)
1027     {
1028         return visitor_(operand);
1029     }
1030 
1031 #else
1032 
1033     template <typename T>
1034     result_type internal_visit(T& operand, int)
1035     {
1036         return visitor_(operand);
1037     }
1038 
1039 #   if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0564))
1040     template <typename T>
1041     result_type internal_visit(const T& operand, int)
1042     {
1043         return visitor_(operand);
1044     }
1045 #   endif //BORLAND
1046 
1047 #endif //RVALUE REFERENCES
1048 
1049 public: // internal visitor interfaces, cont.
1050 
1051     template <typename T>
internal_visit(boost::recursive_wrapper<T> & operand,long)1052     result_type internal_visit(boost::recursive_wrapper<T>& operand, long)
1053     {
1054         return internal_visit( operand.get(), 1L );
1055     }
1056 
1057     template <typename T>
internal_visit(const boost::recursive_wrapper<T> & operand,long)1058     result_type internal_visit(const boost::recursive_wrapper<T>& operand, long)
1059     {
1060         return internal_visit( operand.get(), 1L );
1061     }
1062 
1063     template <typename T>
internal_visit(boost::detail::reference_content<T> & operand,long)1064     result_type internal_visit(boost::detail::reference_content<T>& operand, long)
1065     {
1066         return internal_visit( operand.get(), 1L );
1067     }
1068 
1069     template <typename T>
internal_visit(const boost::detail::reference_content<T> & operand,long)1070     result_type internal_visit(const boost::detail::reference_content<T>& operand, long)
1071     {
1072         return internal_visit( operand.get(), 1L );
1073     }
1074 
1075     template <typename T>
internal_visit(boost::detail::variant::backup_holder<T> & operand,long)1076     result_type internal_visit(boost::detail::variant::backup_holder<T>& operand, long)
1077     {
1078         return internal_visit( operand.get(), 1L );
1079     }
1080 
1081     template <typename T>
internal_visit(const boost::detail::variant::backup_holder<T> & operand,long)1082     result_type internal_visit(const boost::detail::variant::backup_holder<T>& operand, long)
1083     {
1084         return internal_visit( operand.get(), 1L );
1085     }
1086 
1087 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
1088 private:
1089     // silence MSVC warning C4512: assignment operator could not be generated
1090     invoke_visitor& operator= (invoke_visitor const&);
1091 #endif
1092 };
1093 
1094 }} // namespace detail::variant
1095 
1096 ///////////////////////////////////////////////////////////////////////////////
1097 // class template variant (concept inspired by Andrei Alexandrescu)
1098 //
1099 // See docs and boost/variant/variant_fwd.hpp for more information.
1100 //
1101 template <
1102       typename T0_
1103     , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)
1104     >
1105 class variant
1106 {
1107 private: // helpers, for typedefs (below)
1108 
1109     typedef variant wknd_self_t;
1110 
1111     struct is_recursive_
1112         : detail::variant::is_recursive_flag<T0_>
1113     {
1114     };
1115 
1116     typedef typename mpl::eval_if<
1117           is_recursive_
1118         , T0_
1119         , mpl::identity< T0_ >
1120         >::type unwrapped_T0_;
1121 
1122     struct is_sequence_based_
1123         : detail::variant::is_over_sequence<unwrapped_T0_>
1124     {
1125     };
1126 
1127 #if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
1128 
1129 private: // helpers, for typedefs (below)
1130 
1131     typedef typename mpl::eval_if<
1132           is_sequence_based_
1133         , unwrapped_T0_ // over_sequence<...>::type
1134         , detail::variant::make_variant_list<
1135               unwrapped_T0_
1136             , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
1137             >
1138         >::type specified_types;
1139 
1140     BOOST_STATIC_ASSERT((
1141           ::boost::mpl::not_< mpl::empty<specified_types> >::value
1142         ));
1143 
1144 public: // public typedefs
1145     typedef typename mpl::eval_if<
1146           is_recursive_
1147         , mpl::transform<
1148               specified_types
1149             , mpl::protect<
1150                   detail::variant::quoted_enable_recursive<wknd_self_t>
1151                 >
1152             >
1153         , mpl::identity< specified_types >
1154         >::type recursive_enabled_types;    // used by is_variant_constructible_from<> trait
1155 
1156     typedef typename mpl::transform<
1157           recursive_enabled_types
1158         , unwrap_recursive<mpl::_1>
1159         >::type types;
1160 
1161 private: // internal typedefs
1162 
1163     typedef typename mpl::transform<
1164           recursive_enabled_types
1165         , mpl::protect< detail::make_reference_content<> >
1166         >::type internal_types;
1167 
1168     typedef typename mpl::front<
1169           internal_types
1170         >::type internal_T0;
1171 
1172 #else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
1173 
1174 private: // helpers, for typedefs (below)
1175 
1176     typedef unwrapped_T0_ T0;
1177 
1178     #define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
1179         typedef typename mpl::eval_if< \
1180               is_recursive_ \
1181             , detail::variant::enable_recursive< \
1182                   BOOST_PP_CAT(T,N) \
1183                 , wknd_self_t \
1184                 > \
1185             , mpl::identity< BOOST_PP_CAT(T,N) > \
1186             >::type BOOST_PP_CAT(recursive_enabled_T,N); \
1187         /**/
1188 
1189     BOOST_PP_REPEAT(
1190           BOOST_VARIANT_LIMIT_TYPES
1191         , BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1192         , _
1193         )
1194 
1195     #undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1196 
1197     #define BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS(z,N,_) \
1198         typedef typename unwrap_recursive< \
1199               BOOST_PP_CAT(recursive_enabled_T,N) \
1200             >::type BOOST_PP_CAT(public_T,N); \
1201         /**/
1202 
1203     BOOST_PP_REPEAT(
1204           BOOST_VARIANT_LIMIT_TYPES
1205         , BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1206         , _
1207         )
1208 
1209     #undef BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1210 
1211 public: // public typedefs
1212 
1213     typedef typename detail::variant::make_variant_list<
1214           BOOST_VARIANT_ENUM_PARAMS(public_T)
1215         >::type types;
1216 
1217 private: // helpers, for internal typedefs (below)
1218 
1219     #define BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS(z,N,_) \
1220         typedef detail::make_reference_content< \
1221               BOOST_PP_CAT(recursive_enabled_T,N) \
1222             >::type BOOST_PP_CAT(internal_T,N); \
1223         /**/
1224 
1225     BOOST_PP_REPEAT(
1226           BOOST_VARIANT_LIMIT_TYPES
1227         , BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1228         , _
1229         )
1230 
1231     #undef BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1232 
1233 private: // internal typedefs
1234 
1235     typedef typename detail::variant::make_variant_list<
1236           BOOST_VARIANT_ENUM_PARAMS(internal_T)
1237         >::type internal_types;
1238 
1239 private: // static precondition assertions
1240 
1241     // NOTE TO USER :
1242     // variant< type-sequence > syntax is not supported on this compiler!
1243     //
1244     BOOST_MPL_ASSERT_NOT(( is_sequence_based_ ));
1245 
1246 #endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT workaround
1247 
1248 private: // helpers, for representation (below)
1249 
1250     typedef typename detail::variant::find_fallback_type<
1251           internal_types
1252         >::type fallback_type_result_;
1253 
1254     typedef typename fallback_type_result_::first
1255         fallback_type_index_;
1256     typedef typename fallback_type_result_::second
1257         fallback_type_;
1258 
1259     struct has_fallback_type_
1260         : mpl::not_<
1261               is_same< fallback_type_, detail::variant::no_fallback_type >
1262             >
1263     {
1264     };
1265 
1266     typedef has_fallback_type_
1267         never_uses_backup_flag;
1268 
1269     typedef typename detail::variant::make_storage<
1270           internal_types, never_uses_backup_flag
1271         >::type storage_t;
1272 
1273 #ifndef BOOST_NO_CXX11_NOEXCEPT
1274     typedef typename detail::variant::is_variant_move_noexcept_constructible<
1275         internal_types
1276     > variant_move_noexcept_constructible;
1277 
1278     typedef typename detail::variant::is_variant_move_noexcept_assignable<
1279         internal_types
1280     > variant_move_noexcept_assignable;
1281 
1282 #endif
1283 
1284 private: // helpers, for representation (below)
1285 
1286     // which_ on:
1287     // * [0,  size<internal_types>) indicates stack content
1288     // * [-size<internal_types>, 0) indicates pointer to heap backup
1289     // if which_ >= 0:
1290     // * then which() -> which_
1291     // * else which() -> -(which_ + 1)
1292 
1293 #if !defined(BOOST_VARIANT_MINIMIZE_SIZE)
1294 
1295     typedef int which_t;
1296 
1297 #else // defined(BOOST_VARIANT_MINIMIZE_SIZE)
1298 
1299     // [if O1_size available, then attempt which_t size optimization...]
1300     // [select signed char if fewer than SCHAR_MAX types, else signed int:]
1301     typedef typename mpl::eval_if<
1302           mpl::equal_to< mpl::O1_size<internal_types>, mpl::long_<-1> >
1303         , mpl::identity< int >
1304         , mpl::if_<
1305               mpl::less< mpl::O1_size<internal_types>, mpl::int_<SCHAR_MAX> >
1306             , signed char
1307             , int
1308             >
1309         >::type which_t;
1310 
1311 #endif // BOOST_VARIANT_MINIMIZE_SIZE switch
1312 
1313 // representation -- private when possible
1314 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1315     private:
1316 #else
1317     public:
1318 #endif
1319 
1320     which_t which_;
1321     storage_t storage_;
1322 
indicate_which(int which_arg)1323     void indicate_which(int which_arg) BOOST_NOEXCEPT
1324     {
1325         which_ = static_cast<which_t>( which_arg );
1326     }
1327 
indicate_backup_which(int which_arg)1328     void indicate_backup_which(int which_arg) BOOST_NOEXCEPT
1329     {
1330         which_ = static_cast<which_t>( -(which_arg + 1) );
1331     }
1332 
1333 private: // helpers, for queries (below)
1334 
using_backup() const1335     bool using_backup() const BOOST_NOEXCEPT
1336     {
1337         return which_ < 0;
1338     }
1339 
1340 public: // queries
1341 
which() const1342     int which() const BOOST_NOEXCEPT
1343     {
1344         // If using heap backup...
1345         if (using_backup())
1346             // ...then return adjusted which_:
1347             return -(which_ + 1);
1348 
1349         // Otherwise, return which_ directly:
1350         return which_;
1351     }
1352 
1353 private: // helpers, for structors (below)
1354 
1355     struct initializer
1356         : BOOST_VARIANT_AUX_INITIALIZER_T(
1357               recursive_enabled_types, recursive_enabled_T
1358             )
1359     {
1360     };
1361 
destroy_content()1362     void destroy_content() BOOST_NOEXCEPT
1363     {
1364         detail::variant::destroyer visitor;
1365         this->internal_apply_visitor(visitor);
1366     }
1367 
1368 public: // structors
1369 
~variant()1370     ~variant() BOOST_NOEXCEPT
1371     {
1372         destroy_content();
1373     }
1374 
1375     variant()
1376 #if !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130))
BOOST_NOEXCEPT_IF(boost::has_nothrow_constructor<internal_T0>::value)1377               BOOST_NOEXCEPT_IF(boost::has_nothrow_constructor<internal_T0>::value)
1378 #endif
1379     {
1380 #ifdef _MSC_VER
1381 #pragma warning( push )
1382 // behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized
1383 #pragma warning( disable : 4345 )
1384 #endif
1385         // NOTE TO USER :
1386         // Compile error from here indicates that the first bound
1387         // type is not default-constructible, and so variant cannot
1388         // support its own default-construction.
1389         //
1390         new( storage_.address() ) internal_T0();
1391         indicate_which(0); // zero is the index of the first bounded type
1392 #ifdef _MSC_VER
1393 #pragma warning( pop )
1394 #endif
1395     }
1396 
1397 private: // helpers, for structors, cont. (below)
1398 
1399     class convert_copy_into
1400         : public static_visitor<int>
1401     {
1402     private: // representation
1403 
1404         void* storage_;
1405 
1406     public: // structors
1407 
convert_copy_into(void * storage)1408         explicit convert_copy_into(void* storage) BOOST_NOEXCEPT
1409             : storage_(storage)
1410         {
1411         }
1412 
1413     public: // internal visitor interfaces (below)
1414 
1415         template <typename T>
internal_visit(T & operand,int) const1416         int internal_visit(T& operand, int) const
1417         {
1418             // NOTE TO USER :
1419             // Compile error here indicates one of the source variant's types
1420             // cannot be unambiguously converted to the destination variant's
1421             // types (or that no conversion exists).
1422             //
1423             return initializer::initialize(storage_, operand);
1424         }
1425 
1426 #   if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0564))
1427         template <typename T>
internal_visit(const T & operand,int) const1428         result_type internal_visit(const T& operand, int) const
1429         {
1430             return initializer::initialize(storage_, operand);
1431         }
1432 #   endif
1433 
1434         template <typename T>
internal_visit(boost::detail::reference_content<T> & operand,long) const1435         int internal_visit(boost::detail::reference_content<T>& operand, long) const
1436         {
1437             return internal_visit( operand.get(), 1L );
1438         }
1439 
1440         template <typename T>
internal_visit(const boost::detail::reference_content<T> & operand,long) const1441         int internal_visit(const boost::detail::reference_content<T>& operand, long) const
1442         {
1443             return internal_visit( operand.get(), 1L );
1444         }
1445 
1446         template <typename T>
internal_visit(boost::detail::variant::backup_holder<T> & operand,long) const1447         int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
1448         {
1449             return internal_visit( operand.get(), 1L );
1450         }
1451 
1452         template <typename T>
internal_visit(const boost::detail::variant::backup_holder<T> & operand,long) const1453         int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
1454         {
1455             return internal_visit( operand.get(), 1L );
1456         }
1457 
1458         template <typename T>
internal_visit(boost::recursive_wrapper<T> & operand,long) const1459         int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1460         {
1461             return internal_visit( operand.get(), 1L );
1462         }
1463 
1464         template <typename T>
internal_visit(const boost::recursive_wrapper<T> & operand,long) const1465         int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
1466         {
1467             return internal_visit( operand.get(), 1L );
1468         }
1469 
1470     };
1471 
1472     friend class convert_copy_into;
1473 
1474 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1475     class convert_move_into
1476         : public static_visitor<int>
1477     {
1478     private: // representation
1479 
1480         void* storage_;
1481 
1482     public: // structors
1483 
convert_move_into(void * storage)1484         explicit convert_move_into(void* storage) BOOST_NOEXCEPT
1485             : storage_(storage)
1486         {
1487         }
1488 
1489     public: // internal visitor interfaces (below)
1490 
1491         template <typename T>
internal_visit(T & operand,int) const1492         int internal_visit(T& operand, int) const
1493         {
1494             // NOTE TO USER :
1495             // Compile error here indicates one of the source variant's types
1496             // cannot be unambiguously converted to the destination variant's
1497             // types (or that no conversion exists).
1498             //
1499             return initializer::initialize(storage_, detail::variant::move(operand) );
1500         }
1501 
1502         template <typename T>
internal_visit(boost::detail::reference_content<T> & operand,long) const1503         int internal_visit(boost::detail::reference_content<T>& operand, long) const
1504         {
1505             return internal_visit( operand.get(), 1L );
1506         }
1507 
1508         template <typename T>
internal_visit(const boost::detail::reference_content<T> & operand,long) const1509         int internal_visit(const boost::detail::reference_content<T>& operand, long) const
1510         {
1511             return internal_visit( operand.get(), 1L );
1512         }
1513 
1514         template <typename T>
internal_visit(boost::detail::variant::backup_holder<T> & operand,long) const1515         int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
1516         {
1517             return internal_visit( operand.get(), 1L );
1518         }
1519 
1520         template <typename T>
internal_visit(const boost::detail::variant::backup_holder<T> & operand,long) const1521         int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
1522         {
1523             return internal_visit( operand.get(), 1L );
1524         }
1525 
1526         template <typename T>
internal_visit(boost::recursive_wrapper<T> & operand,long) const1527         int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1528         {
1529             return internal_visit( operand.get(), 1L );
1530         }
1531 
1532         template <typename T>
internal_visit(const boost::recursive_wrapper<T> & operand,long) const1533         int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
1534         {
1535             return internal_visit( operand.get(), 1L );
1536         }
1537     };
1538 
1539     friend class convert_move_into;
1540 #endif
1541 
1542 private: // helpers, for structors, below
1543 
1544     template <typename T>
convert_construct(T & operand,int,mpl::false_=mpl::false_ ())1545     void convert_construct(
1546           T& operand
1547         , int
1548         , mpl::false_ = mpl::false_() // is_foreign_variant
1549         )
1550     {
1551         // NOTE TO USER :
1552         // Compile error here indicates that the given type is not
1553         // unambiguously convertible to one of the variant's types
1554         // (or that no conversion exists).
1555         //
1556         indicate_which(
1557               initializer::initialize(
1558                   storage_.address()
1559                 , operand
1560                 )
1561             );
1562     }
1563 
1564 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1565     template <typename T>
convert_construct(T && operand,int,mpl::false_=mpl::false_ ())1566     typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type convert_construct(
1567           T&& operand
1568         , int
1569         , mpl::false_ = mpl::false_() // is_foreign_variant
1570         )
1571     {
1572         // NOTE TO USER :
1573         // Compile error here indicates that the given type is not
1574         // unambiguously convertible to one of the variant's types
1575         // (or that no conversion exists).
1576         //
1577         indicate_which(
1578               initializer::initialize(
1579                   storage_.address()
1580                 , detail::variant::move(operand)
1581                 )
1582             );
1583     }
1584 #endif
1585 
1586     template <typename Variant>
convert_construct(Variant & operand,long,mpl::true_)1587     void convert_construct(
1588           Variant& operand
1589         , long
1590         , mpl::true_// is_foreign_variant
1591         )
1592     {
1593         convert_copy_into visitor(storage_.address());
1594         indicate_which(
1595               operand.internal_apply_visitor(visitor)
1596             );
1597     }
1598 
1599 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1600     template <typename Variant>
convert_construct(Variant && operand,long,mpl::true_)1601     typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct(
1602           Variant&& operand
1603         , long
1604         , mpl::true_// is_foreign_variant
1605         )
1606     {
1607         convert_move_into visitor(storage_.address());
1608         indicate_which(
1609               operand.internal_apply_visitor(visitor)
1610             );
1611     }
1612 #endif
1613 
1614     template <typename Variant>
convert_construct_variant(Variant & operand)1615     void convert_construct_variant(Variant& operand)
1616     {
1617         // [Determine if the given variant is itself a bounded type, or if its
1618         //  content needs to be converted (i.e., it is a 'foreign' variant):]
1619         //
1620 
1621         typedef typename mpl::find_if<
1622               types
1623             , is_same<
1624                   add_const<mpl::_1>
1625                 , const Variant
1626                 >
1627             >::type found_it;
1628 
1629         typedef typename mpl::end<types>::type not_found;
1630         typedef typename is_same<
1631               found_it, not_found
1632             >::type is_foreign_variant;
1633 
1634         // Convert construct from operand:
1635         convert_construct(
1636               operand, 1L
1637             , is_foreign_variant()
1638             );
1639     }
1640 
1641 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1642     template <typename Variant>
convert_construct_variant(Variant && operand)1643     typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct_variant(Variant&& operand)
1644     {
1645         // [Determine if the given variant is itself a bounded type, or if its
1646         //  content needs to be converted (i.e., it is a 'foreign' variant):]
1647         //
1648 
1649         typedef typename mpl::find_if<
1650               types
1651             , is_same<
1652                   add_const<mpl::_1>
1653                 , const Variant
1654                 >
1655             >::type found_it;
1656 
1657         typedef typename mpl::end<types>::type not_found;
1658         typedef typename is_same<
1659               found_it, not_found
1660             >::type is_foreign_variant;
1661 
1662         // Convert move construct from operand:
1663         convert_construct(
1664               detail::variant::move(operand), 1L
1665             , is_foreign_variant()
1666             );
1667     }
1668 #endif
1669 
1670     template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1671     typename boost::enable_if<mpl::or_<
1672         boost::is_same<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>, variant>,
1673         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)1674     > >::type convert_construct(
1675           boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1676         , long
1677         )
1678     {
1679         convert_construct_variant(operand);
1680     }
1681 
1682     template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1683     typename boost::enable_if<mpl::or_<
1684         boost::is_same<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>, variant>,
1685         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)1686     > >::type convert_construct(
1687           const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1688         , long
1689         )
1690     {
1691         convert_construct_variant(operand);
1692     }
1693 
1694 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1695     template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1696     typename boost::enable_if<mpl::or_<
1697         boost::is_same<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>, variant>,
1698         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)1699     > >::type convert_construct(
1700           boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&& operand
1701         , long
1702         )
1703     {
1704         convert_construct_variant( detail::variant::move(operand) );
1705     }
1706 #endif
1707 
1708 public: // structors, cont.
1709 
1710     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_>>,bool>::type=true)1711     variant(const T& operand,
1712         typename boost::enable_if<mpl::or_<
1713             mpl::and_<
1714                 mpl::not_< boost::is_same<T, variant> >,
1715                 boost::detail::variant::is_variant_constructible_from<const T&, internal_types>
1716             >,
1717             boost::is_same<T, boost::recursive_variant_> >,
1718             bool >::type = true)
1719     {
1720         convert_construct(operand, 1L);
1721     }
1722 
1723     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_>>,bool>::type=true)1724     variant(
1725           T& operand
1726         , typename boost::enable_if<mpl::or_<
1727             mpl::and_<
1728                 mpl::not_< is_const<T> >,
1729                 mpl::not_< boost::is_same<T, variant> >,
1730                 boost::detail::variant::is_variant_constructible_from<T&, internal_types>
1731             >,
1732             boost::is_same<T, boost::recursive_variant_> >,
1733             bool >::type = true
1734         )
1735     {
1736         convert_construct(operand, 1L);
1737     }
1738 
1739 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1740     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_>>,bool>::type=true)1741     variant(T&& operand,
1742         typename boost::enable_if<mpl::or_<
1743             mpl::and_<
1744                 boost::is_rvalue_reference<T&&>,
1745                 mpl::not_< boost::is_const<T> >,
1746                 mpl::not_< boost::is_same<T, variant> >,
1747                 boost::detail::variant::is_variant_constructible_from<T&&, internal_types>
1748             >,
1749             boost::is_same<T, boost::recursive_variant_> >,
1750             bool >::type = true)
1751     {
1752         convert_construct( detail::variant::move(operand), 1L);
1753     }
1754 #endif
1755 
1756 public: // structors, cont.
1757 
1758     // [MSVC6 requires copy constructor appear after template constructors]
variant(const variant & operand)1759     variant(const variant& operand)
1760     {
1761         // Copy the value of operand into *this...
1762         detail::variant::copy_into visitor( storage_.address() );
1763         operand.internal_apply_visitor(visitor);
1764 
1765         // ...and activate the *this's primary storage on success:
1766         indicate_which(operand.which());
1767     }
1768 
1769 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value)1770     variant(variant&& operand) BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value)
1771     {
1772         // Move the value of operand into *this...
1773         detail::variant::move_into visitor( storage_.address() );
1774         operand.internal_apply_visitor(visitor);
1775 
1776         // ...and activate the *this's primary storage on success:
1777         indicate_which(operand.which());
1778     }
1779 #endif
1780 
1781 private: // helpers, for modifiers (below)
1782 
1783 #   if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1784     template <typename Variant>
1785     friend class detail::variant::backup_assigner;
1786 #   endif
1787 
1788     // class assigner
1789     //
1790     // Internal visitor that "assigns" the visited value to the given variant
1791     // by appropriate destruction and copy-construction.
1792     //
1793 
1794     class assigner
1795         : public static_visitor<>
1796     {
1797     protected: // representation
1798 
1799         variant& lhs_;
1800         const int rhs_which_;
1801 
1802     public: // structors
1803 
assigner(variant & lhs,int rhs_which)1804         assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
1805             : lhs_(lhs)
1806             , rhs_which_(rhs_which)
1807         {
1808         }
1809 
1810     protected: // helpers, for internal visitor interface (below)
1811 
1812         template <typename RhsT, typename B1, typename B2>
assign_impl(const RhsT & rhs_content,mpl::true_,B1,B2) const1813         void assign_impl(
1814               const RhsT& rhs_content
1815             , mpl::true_ // has_nothrow_copy
1816             , B1 // is_nothrow_move_constructible
1817             , B2 // has_fallback_type
1818             ) const BOOST_NOEXCEPT
1819         {
1820             // Destroy lhs's content...
1821             lhs_.destroy_content(); // nothrow
1822 
1823             // ...copy rhs content into lhs's storage...
1824             new(lhs_.storage_.address())
1825                 RhsT( rhs_content ); // nothrow
1826 
1827             // ...and indicate new content type:
1828             lhs_.indicate_which(rhs_which_); // nothrow
1829         }
1830 
1831         template <typename RhsT, typename B>
assign_impl(const RhsT & rhs_content,mpl::false_,mpl::true_,B) const1832         void assign_impl(
1833               const RhsT& rhs_content
1834             , mpl::false_ // has_nothrow_copy
1835             , mpl::true_ // is_nothrow_move_constructible
1836             , B // has_fallback_type
1837             ) const
1838         {
1839             // Attempt to make a temporary copy (so as to move it below)...
1840             RhsT temp(rhs_content);
1841 
1842             // ...and upon success destroy lhs's content...
1843             lhs_.destroy_content(); // nothrow
1844 
1845             // ...move the temporary copy into lhs's storage...
1846             new(lhs_.storage_.address())
1847                 RhsT( detail::variant::move(temp) ); // nothrow
1848 
1849             // ...and indicate new content type:
1850             lhs_.indicate_which(rhs_which_); // nothrow
1851         }
1852 
construct_fallback() const1853         void construct_fallback() const BOOST_NOEXCEPT {
1854             // In case of failure, default-construct fallback type in lhs's storage...
1855             new (lhs_.storage_.address())
1856                 fallback_type_; // nothrow
1857 
1858             // ...indicate construction of fallback type...
1859             lhs_.indicate_which(
1860                   BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value
1861                 ); // nothrow
1862         }
1863 
1864         template <typename RhsT>
assign_impl(const RhsT & rhs_content,mpl::false_,mpl::false_,mpl::true_) const1865         void assign_impl(
1866               const RhsT& rhs_content
1867             , mpl::false_ // has_nothrow_copy
1868             , mpl::false_ // is_nothrow_move_constructible
1869             , mpl::true_ // has_fallback_type
1870             ) const
1871         {
1872             // Destroy lhs's content...
1873             lhs_.destroy_content(); // nothrow
1874 
1875             BOOST_TRY
1876             {
1877                 // ...and attempt to copy rhs's content into lhs's storage:
1878                 new(lhs_.storage_.address())
1879                     RhsT( rhs_content );
1880             }
1881             BOOST_CATCH (...)
1882             {
1883                 construct_fallback();
1884 
1885                 // ...and rethrow:
1886                 BOOST_RETHROW;
1887             }
1888             BOOST_CATCH_END
1889 
1890             // In the event of success, indicate new content type:
1891             lhs_.indicate_which(rhs_which_); // nothrow
1892         }
1893 
1894         template <typename RhsT>
assign_impl(const RhsT & rhs_content,mpl::false_,mpl::false_,mpl::false_) const1895         void assign_impl(
1896               const RhsT& rhs_content
1897             , mpl::false_ // has_nothrow_copy
1898             , mpl::false_ // is_nothrow_move_constructible
1899             , mpl::false_ // has_fallback_type
1900             ) const
1901         {
1902             detail::variant::backup_assigner<wknd_self_t>
1903                 visitor(lhs_, rhs_which_, rhs_content);
1904             lhs_.internal_apply_visitor(visitor);
1905         }
1906 
1907     public: // internal visitor interfaces
1908 
1909         template <typename RhsT>
internal_visit(const RhsT & rhs_content,int) const1910         void internal_visit(const RhsT& rhs_content, int) const
1911         {
1912             typedef typename has_nothrow_copy<RhsT>::type
1913                 nothrow_copy;
1914             typedef typename mpl::or_< // reduces compile-time
1915                   nothrow_copy
1916                 , is_nothrow_move_constructible<RhsT>
1917                 >::type nothrow_move_constructor;
1918 
1919             assign_impl(
1920                   rhs_content
1921                 , nothrow_copy()
1922                 , nothrow_move_constructor()
1923                 , has_fallback_type_()
1924                 );
1925         }
1926 
1927 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
1928     private:
1929         // silence MSVC warning C4512: assignment operator could not be generated
1930         assigner& operator= (assigner const&);
1931 #endif
1932     };
1933 
1934     friend class assigner;
1935 
1936 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1937     // class move_assigner
1938     //
1939     // Internal visitor that "move assigns" the visited value to the given variant
1940     // by appropriate destruction and move-construction.
1941     //
1942 
1943     class move_assigner
1944         : public assigner
1945     {
1946     public: // structors
1947 
move_assigner(variant & lhs,int rhs_which)1948         move_assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
1949             : assigner(lhs, rhs_which)
1950         {
1951         }
1952 
1953     private: // helpers, for internal visitor interface (below)
1954 
1955         template <typename RhsT, typename B2>
assign_impl(RhsT & rhs_content,mpl::true_,mpl::false_,B2) const1956         void assign_impl(
1957               RhsT& rhs_content
1958             , mpl::true_ // has_nothrow_copy
1959             , mpl::false_ // is_nothrow_move_constructible
1960             , B2 // has_fallback_type
1961             ) const BOOST_NOEXCEPT
1962         {
1963             assigner::assign_impl(rhs_content, mpl::true_(), mpl::false_(), B2());
1964         }
1965 
1966         template <typename RhsT, typename B, typename B2>
assign_impl(RhsT & rhs_content,B,mpl::true_,B2) const1967         void assign_impl(
1968               RhsT& rhs_content
1969             , B // has_nothrow_copy
1970             , mpl::true_ // is_nothrow_move_constructible
1971             , B2 // has_fallback_type
1972             ) const BOOST_NOEXCEPT
1973         {
1974             // ...destroy lhs's content...
1975             assigner::lhs_.destroy_content(); // nothrow
1976 
1977             // ...move the rhs_content into lhs's storage...
1978             new(assigner::lhs_.storage_.address())
1979                 RhsT( detail::variant::move(rhs_content) ); // nothrow
1980 
1981             // ...and indicate new content type:
1982             assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
1983         }
1984 
1985         template <typename RhsT>
assign_impl(RhsT & rhs_content,mpl::false_,mpl::false_,mpl::true_) const1986         void assign_impl(
1987               RhsT& rhs_content
1988             , mpl::false_ // has_nothrow_copy
1989             , mpl::false_ // is_nothrow_move_constructible
1990             , mpl::true_ // has_fallback_type
1991             ) const
1992         {
1993             // Destroy lhs's content...
1994             assigner::lhs_.destroy_content(); // nothrow
1995 
1996             BOOST_TRY
1997             {
1998                 // ...and attempt to copy rhs's content into lhs's storage:
1999                 new(assigner::lhs_.storage_.address())
2000                     RhsT( detail::variant::move(rhs_content) );
2001             }
2002             BOOST_CATCH (...)
2003             {
2004                 assigner::construct_fallback();
2005 
2006                 // ...and rethrow:
2007                 BOOST_RETHROW;
2008             }
2009             BOOST_CATCH_END
2010 
2011             // In the event of success, indicate new content type:
2012             assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
2013         }
2014 
2015         template <typename RhsT>
assign_impl(RhsT & rhs_content,mpl::false_,mpl::false_,mpl::false_) const2016         void assign_impl(
2017               RhsT& rhs_content
2018             , mpl::false_ // has_nothrow_copy
2019             , mpl::false_ // is_nothrow_move_constructible
2020             , mpl::false_ // has_fallback_type
2021             ) const
2022         {
2023             assigner::assign_impl(rhs_content, mpl::false_(), mpl::false_(), mpl::false_());
2024         }
2025 
2026     public: // internal visitor interfaces
2027 
2028         template <typename RhsT>
internal_visit(RhsT & rhs_content,int) const2029         void internal_visit(RhsT& rhs_content, int) const
2030         {
2031             typedef typename is_nothrow_move_constructible<RhsT>::type
2032                 nothrow_move_constructor;
2033             typedef typename mpl::or_< // reduces compile-time
2034                   nothrow_move_constructor
2035                 , has_nothrow_copy<RhsT>
2036                 >::type nothrow_copy;
2037 
2038             assign_impl(
2039                   rhs_content
2040                 , nothrow_copy()
2041                 , nothrow_move_constructor()
2042                 , has_fallback_type_()
2043                 );
2044         }
2045 
2046 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
2047     private:
2048         // silence MSVC warning C4512: assignment operator could not be generated
2049         move_assigner& operator= (move_assigner const&);
2050 #endif
2051     };
2052 
2053     friend class move_assigner;
2054 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2055 
variant_assign(const variant & rhs)2056     void variant_assign(const variant& rhs)
2057     {
2058         // If the contained types are EXACTLY the same...
2059         if (which_ == rhs.which_)
2060         {
2061             // ...then assign rhs's storage to lhs's content:
2062             detail::variant::assign_storage visitor(rhs.storage_.address());
2063             this->internal_apply_visitor(visitor);
2064         }
2065         else
2066         {
2067             // Otherwise, perform general (copy-based) variant assignment:
2068             assigner visitor(*this, rhs.which());
2069             rhs.internal_apply_visitor(visitor);
2070         }
2071     }
2072 
2073 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
variant_assign(variant && rhs)2074     void variant_assign(variant&& rhs)
2075     {
2076         // If the contained types are EXACTLY the same...
2077         if (which_ == rhs.which_)
2078         {
2079             // ...then move rhs's storage to lhs's content:
2080             detail::variant::move_storage visitor(rhs.storage_.address());
2081             this->internal_apply_visitor(visitor);
2082         }
2083         else
2084         {
2085             // Otherwise, perform general (move-based) variant assignment:
2086             move_assigner visitor(*this, rhs.which());
2087             rhs.internal_apply_visitor(visitor);
2088         }
2089     }
2090 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2091 
2092 private: // helpers, for modifiers (below)
2093 
2094     template <typename T>
assign(const T & rhs)2095     void assign(const T& rhs)
2096     {
2097         // If direct T-to-T assignment is not possible...
2098         detail::variant::direct_assigner<T> direct_assign(rhs);
2099         if (this->apply_visitor(direct_assign) == false)
2100         {
2101             // ...then convert rhs to variant and assign:
2102             //
2103             // While potentially inefficient, the following construction of a
2104             // variant allows T as any type convertible to one of the bounded
2105             // types without excessive code redundancy.
2106             //
2107             variant temp(rhs);
2108             variant_assign( detail::variant::move(temp) );
2109         }
2110     }
2111 
2112 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2113     template <typename T>
move_assign(T && rhs)2114     void move_assign(T&& rhs)
2115     {
2116         // If direct T-to-T move assignment is not possible...
2117         detail::variant::direct_mover<T> direct_move(rhs);
2118         if (this->apply_visitor(direct_move) == false)
2119         {
2120             // ...then convert rhs to variant and assign:
2121             //
2122             // While potentially inefficient, the following construction of a
2123             // variant allows T as any type convertible to one of the bounded
2124             // types without excessive code redundancy.
2125             //
2126             variant temp( detail::variant::move(rhs) );
2127             variant_assign( detail::variant::move(temp) );
2128         }
2129     }
2130 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2131 
2132 public: // modifiers
2133 
2134 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2135     template <class T>
2136     typename boost::enable_if<
2137         boost::mpl::and_<
2138             boost::is_rvalue_reference<T&&>,
2139             mpl::not_< boost::is_const<T> >,
2140             boost::detail::variant::is_variant_constructible_from<T&&, internal_types>
2141         >,
2142         variant&
operator =(T && rhs)2143     >::type operator=(T&& rhs)
2144     {
2145         move_assign( detail::variant::move(rhs) );
2146         return *this;
2147     }
2148 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2149 
2150     template <typename T>
2151     typename boost::enable_if<
2152         mpl::or_<
2153             boost::is_same<T, variant>,
2154             boost::detail::variant::is_variant_constructible_from<const T&, internal_types>
2155         >,
2156         variant&
operator =(const T & rhs)2157     >::type operator=(const T& rhs)
2158     {
2159         assign(rhs);
2160         return *this;
2161     }
2162 
2163     // [MSVC6 requires copy assign appear after templated operator=]
operator =(const variant & rhs)2164     variant& operator=(const variant& rhs)
2165     {
2166         variant_assign(rhs);
2167         return *this;
2168     }
2169 
2170 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
operator =(variant && rhs)2171     variant& operator=(variant&& rhs)
2172 #if !defined(__GNUC__) || (__GNUC__ != 4) || (__GNUC_MINOR__ > 6) || defined(__clang__)
2173         BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value && variant_move_noexcept_assignable::type::value)
2174 #endif
2175     {
2176         variant_assign( detail::variant::move(rhs) );
2177         return *this;
2178     }
2179 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2180 
swap(variant & rhs)2181     void swap(variant& rhs)
2182     {
2183         // If the contained types are the same...
2184         if (which() == rhs.which())
2185         {
2186             // ...then swap the values directly:
2187             detail::variant::swap_with<variant> visitor(rhs);
2188             this->apply_visitor(visitor);
2189         }
2190         else
2191         {
2192             // ...otherwise, perform general variant swap:
2193             variant tmp( detail::variant::move(rhs) );
2194             rhs = detail::variant::move(*this);
2195             *this = detail::variant::move(tmp);
2196         }
2197     }
2198 
2199 public: // queries
2200 
2201     //
2202     // NOTE: member which() defined above.
2203     //
2204 
empty() const2205     bool empty() const BOOST_NOEXCEPT
2206     {
2207         return false;
2208     }
2209 
type() const2210     const boost::typeindex::type_info& type() const
2211     {
2212         detail::variant::reflect visitor;
2213         return this->apply_visitor(visitor);
2214     }
2215 
2216 public: // prevent comparison with foreign types
2217 
2218     template <typename U>
operator ==(const U &) const2219     void operator==(const U&) const
2220     {
2221         BOOST_STATIC_ASSERT( false && sizeof(U) );
2222     }
2223 
2224     template <typename U>
operator <(const U &) const2225     void operator<(const U&) const
2226     {
2227         BOOST_STATIC_ASSERT( false && sizeof(U) );
2228     }
2229 
2230     template <typename U>
operator !=(const U &) const2231     void operator!=(const U&) const
2232     {
2233         BOOST_STATIC_ASSERT( false && sizeof(U) );
2234     }
2235 
2236     template <typename U>
operator >(const U &) const2237     void operator>(const U&) const
2238     {
2239         BOOST_STATIC_ASSERT( false && sizeof(U) );
2240     }
2241 
2242     template <typename U>
operator <=(const U &) const2243     void operator<=(const U&) const
2244     {
2245         BOOST_STATIC_ASSERT( false && sizeof(U) );
2246     }
2247 
2248     template <typename U>
operator >=(const U &) const2249     void operator>=(const U&) const
2250     {
2251         BOOST_STATIC_ASSERT( false && sizeof(U) );
2252     }
2253 
2254 public: // comparison operators
2255 
2256     // [MSVC6 requires these operators appear after template operators]
2257 
operator ==(const variant & rhs) const2258     bool operator==(const variant& rhs) const
2259     {
2260         if (this->which() != rhs.which())
2261             return false;
2262 
2263         detail::variant::comparer<
2264               variant, detail::variant::equal_comp
2265             > visitor(*this);
2266         return rhs.apply_visitor(visitor);
2267     }
2268 
operator <(const variant & rhs) const2269     bool operator<(const variant& rhs) const
2270     {
2271         //
2272         // Dirk Schreib suggested this collating order.
2273         //
2274 
2275         if (this->which() != rhs.which())
2276             return this->which() < rhs.which();
2277 
2278         detail::variant::comparer<
2279               variant, detail::variant::less_comp
2280             > visitor(*this);
2281         return rhs.apply_visitor(visitor);
2282     }
2283 
2284     ///////////////////////////////////////////////////////////////////////////////
2285     // comparison operators != > <= >=
operator !=(const variant & rhs) const2286     inline bool operator!=(const variant& rhs) const
2287     {
2288         return !(*this == rhs);
2289     }
2290 
operator >(const variant & rhs) const2291     inline bool operator>(const variant& rhs) const
2292     {
2293         return rhs < *this;
2294     }
2295 
operator <=(const variant & rhs) const2296     inline bool operator<=(const variant& rhs) const
2297     {
2298         return !(*this > rhs);
2299     }
2300 
operator >=(const variant & rhs) const2301     inline bool operator>=(const variant& rhs) const
2302     {
2303         return !(*this < rhs);
2304     }
2305 
2306 // helpers, for visitation support (below) -- private when possible
2307 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2308 
2309     template < BOOST_VARIANT_ENUM_PARAMS(typename U) >
2310     friend class variant;
2311 
2312 private:
2313 
2314 #else// defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2315 
2316 public:
2317 
2318 #endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2319 
2320     template <typename Visitor, typename VoidPtrCV>
2321     BOOST_FORCEINLINE static typename Visitor::result_type
internal_apply_visitor_impl(int internal_which,int logical_which,Visitor & visitor,VoidPtrCV storage)2322     internal_apply_visitor_impl(
2323           int internal_which
2324         , int logical_which
2325         , Visitor& visitor
2326         , VoidPtrCV storage
2327         )
2328     {
2329         typedef mpl::int_<0> first_which;
2330         typedef typename mpl::begin<internal_types>::type first_it;
2331         typedef typename mpl::end<internal_types>::type last_it;
2332 
2333         typedef detail::variant::visitation_impl_step<
2334               first_it, last_it
2335             > first_step;
2336 
2337         return detail::variant::visitation_impl(
2338               internal_which, logical_which
2339             , visitor, storage, mpl::false_()
2340             , never_uses_backup_flag()
2341             , static_cast<first_which*>(0), static_cast<first_step*>(0)
2342             );
2343     }
2344 
2345     template <typename Visitor>
2346     BOOST_FORCEINLINE typename Visitor::result_type
internal_apply_visitor(Visitor & visitor)2347     internal_apply_visitor(Visitor& visitor)
2348     {
2349         return internal_apply_visitor_impl(
2350               which_, which(), visitor, storage_.address()
2351             );
2352     }
2353 
2354     template <typename Visitor>
2355     BOOST_FORCEINLINE typename Visitor::result_type
internal_apply_visitor(Visitor & visitor) const2356     internal_apply_visitor(Visitor& visitor) const
2357     {
2358         return internal_apply_visitor_impl(
2359               which_, which(), visitor, storage_.address()
2360             );
2361     }
2362 
2363 public: // visitation support
2364 
2365 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
2366 
2367     template <typename Visitor>
2368     typename Visitor::result_type
apply_visitor(Visitor & visitor)2369     apply_visitor(Visitor& visitor) &&
2370     {
2371         detail::variant::invoke_visitor<Visitor, true> invoker(visitor);
2372         return this->internal_apply_visitor(invoker);
2373     }
2374 
2375     template <typename Visitor>
2376     typename Visitor::result_type
apply_visitor(Visitor & visitor) const2377     apply_visitor(Visitor& visitor) const&&
2378     {
2379         detail::variant::invoke_visitor<Visitor, true> invoker(visitor);
2380         return this->internal_apply_visitor(invoker);
2381     }
2382 
2383 #endif
2384 
2385     template <typename Visitor>
2386     typename Visitor::result_type
apply_visitor(Visitor & visitor)2387     apply_visitor(Visitor& visitor)
2388 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
2389     &
2390 #endif
2391     {
2392         detail::variant::invoke_visitor<Visitor, false> invoker(visitor);
2393         return this->internal_apply_visitor(invoker);
2394     }
2395 
2396     template <typename Visitor>
2397     typename Visitor::result_type
apply_visitor(Visitor & visitor) const2398     apply_visitor(Visitor& visitor) const
2399 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
2400     &
2401 #endif
2402     {
2403         detail::variant::invoke_visitor<Visitor, false> invoker(visitor);
2404         return this->internal_apply_visitor(invoker);
2405     }
2406 
2407 }; // class variant
2408 
2409 ///////////////////////////////////////////////////////////////////////////////
2410 // metafunction make_variant_over
2411 //
2412 // See docs and boost/variant/variant_fwd.hpp for more information.
2413 //
2414 template <typename Types>
2415 struct make_variant_over
2416 {
2417 private: // precondition assertions
2418 
2419     BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value ));
2420     typedef typename boost::mpl::insert_range<
2421       boost::mpl::list<>
2422     , boost::mpl::end< boost::mpl::list<> >::type
2423     , Types
2424     >::type copied_sequence_t;
2425 
2426 public: // metafunction result
2427 
2428     typedef variant<
2429           detail::variant::over_sequence<copied_sequence_t>
2430         > type;
2431 
2432 };
2433 
2434 ///////////////////////////////////////////////////////////////////////////////
2435 // function template swap
2436 //
2437 // Swaps two variants of the same type (i.e., identical specification).
2438 //
2439 template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
swap(variant<BOOST_VARIANT_ENUM_PARAMS (T)> & lhs,variant<BOOST_VARIANT_ENUM_PARAMS (T)> & rhs)2440 inline void swap(
2441       variant< BOOST_VARIANT_ENUM_PARAMS(T) >& lhs
2442     , variant< BOOST_VARIANT_ENUM_PARAMS(T) >& rhs
2443     )
2444 {
2445     lhs.swap(rhs);
2446 }
2447 
2448 } // namespace boost
2449 
2450 // implementation additions
2451 
2452 #if !defined(BOOST_NO_IOSTREAM)
2453 #include <boost/variant/detail/variant_io.hpp>
2454 #endif // BOOST_NO_IOSTREAM
2455 
2456 #endif // BOOST_VARIANT_VARIANT_HPP
2457