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