]> git.lyx.org Git - lyx.git/blob - 3rdparty/boost/boost/variant/variant.hpp
Update to boost 1.72
[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-2019 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/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/integer/common_factor_ct.hpp>
44 #include <boost/static_assert.hpp>
45 #include <boost/preprocessor/cat.hpp>
46 #include <boost/preprocessor/repeat.hpp>
47 #include <boost/type_traits/alignment_of.hpp>
48 #include <boost/type_traits/add_const.hpp>
49 #include <boost/type_traits/has_nothrow_constructor.hpp>
50 #include <boost/type_traits/has_nothrow_copy.hpp>
51 #include <boost/type_traits/is_nothrow_move_assignable.hpp>
52 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
53 #include <boost/type_traits/is_const.hpp>
54 #include <boost/type_traits/is_same.hpp>
55 #include <boost/type_traits/is_rvalue_reference.hpp>
56 #include <boost/type_traits/is_constructible.hpp>
57 #include <boost/type_traits/add_lvalue_reference.hpp>
58 #include <boost/utility/enable_if.hpp>
59 #include <boost/utility/declval.hpp>
60 #include <boost/variant/recursive_wrapper_fwd.hpp>
61 #include <boost/variant/static_visitor.hpp>
62
63 #include <boost/mpl/assert.hpp>
64 #include <boost/mpl/begin_end.hpp>
65 #include <boost/mpl/bool.hpp>
66 #include <boost/mpl/deref.hpp>
67 #include <boost/mpl/empty.hpp>
68 #include <boost/mpl/eval_if.hpp>
69 #include <boost/mpl/find_if.hpp>
70 #include <boost/mpl/fold.hpp>
71 #include <boost/mpl/front.hpp>
72 #include <boost/mpl/identity.hpp>
73 #include <boost/mpl/if.hpp>
74 #include <boost/mpl/insert_range.hpp>
75 #include <boost/mpl/int.hpp>
76 #include <boost/mpl/is_sequence.hpp>
77 #include <boost/mpl/iterator_range.hpp>
78 #include <boost/mpl/iter_fold_if.hpp>
79 #include <boost/mpl/list.hpp>
80 #include <boost/mpl/logical.hpp>
81 #include <boost/mpl/max_element.hpp>
82 #include <boost/mpl/next.hpp>
83 #include <boost/mpl/not.hpp>
84 #include <boost/mpl/pair.hpp>
85 #include <boost/mpl/protect.hpp>
86 #include <boost/mpl/push_front.hpp>
87 #include <boost/mpl/same_as.hpp>
88 #include <boost/mpl/size_t.hpp>
89 #include <boost/mpl/sizeof.hpp>
90 #include <boost/mpl/transform.hpp>
91
92 ///////////////////////////////////////////////////////////////////////////////
93 // Implementation Macros:
94 //
95 // BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
96 //   Defined in boost/variant/detail/visitation_impl.hpp.
97 //
98 // BOOST_VARIANT_MINIMIZE_SIZE
99 //   When #defined, implementation employs all known means to minimize the
100 //   size of variant obje   cts. However, often unsuccessful due to alignment
101 //   issues, and potentially harmful to runtime speed, so not enabled by
102 //   default. (TODO: Investigate further.)
103
104 #if defined(BOOST_VARIANT_MINIMIZE_SIZE)
105 #   include <climits> // for SCHAR_MAX
106 #   include <boost/mpl/eval_if.hpp>
107 #   include <boost/mpl/equal_to.hpp>
108 #   include <boost/mpl/identity.hpp>
109 #   include <boost/mpl/int.hpp>
110 #   include <boost/mpl/if.hpp>
111 #   include <boost/mpl/less.hpp>
112 #   include <boost/mpl/long.hpp>
113 #   include <boost/mpl/O1_size.hpp>
114 #endif
115
116
117 namespace boost {
118
119 namespace detail { namespace variant {
120
121 ///////////////////////////////////////////////////////////////////////////////
122 // (detail) metafunction max_value
123 //
124 // Finds the maximum value of the unary metafunction F over Sequence.
125 //
126 template <typename Sequence, typename F>
127 struct max_value
128 {
129 private: // helpers, for metafunction result (below)
130
131     typedef typename mpl::transform1<Sequence, F>::type transformed_;
132     typedef typename mpl::max_element<transformed_
133           
134         >::type max_it;
135
136 public: // metafunction result
137
138     typedef typename mpl::deref<max_it>::type
139         type;
140
141 };
142
143 struct add_alignment
144 {
145     template <typename State, typename Item>
146     struct apply
147         : mpl::size_t<
148               ::boost::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(__BORLANDC__, BOOST_TESTED_AT(0x0551))
351
352     typedef typename mpl::fold<
353           types
354         , mpl::size_t<1>
355         , add_alignment
356         >::type max_alignment;
357
358 #else // borland
359
360     // temporary workaround -- use maximal alignment
361     typedef mpl::size_t< -1 > max_alignment;
362
363 #endif // borland workaround
364
365 public: // metafunction result
366
367     typedef ::boost::aligned_storage<
368           BOOST_MPL_AUX_VALUE_WKND(max_size)::value
369         , BOOST_MPL_AUX_VALUE_WKND(max_alignment)::value
370         > type;
371 };
372
373 ///////////////////////////////////////////////////////////////////////////////
374 // (detail) class destroyer
375 //
376 // Internal visitor that destroys the value it visits.
377 //
378 struct destroyer
379     : public static_visitor<>
380 {
381 public: // visitor interfaces
382
383     template <typename T>
384     void internal_visit(T& operand, int) const BOOST_NOEXCEPT
385     {
386         operand.~T(); // must be noexcept
387
388 #if BOOST_WORKAROUND(__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
410     T& operator()(T& operand) const BOOST_NOEXCEPT
411     {
412         return operand;
413     }
414
415     template <typename U>
416     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
437     explicit copy_into(void* storage) BOOST_NOEXCEPT
438         : storage_(storage)
439     {
440     }
441
442 public: // internal visitor interface
443
444     template <typename T>
445     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>
451     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>
457     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
479     explicit move_into(void* storage) BOOST_NOEXCEPT
480         : storage_(storage)
481     {
482     }
483
484 public: // internal visitor interface
485
486     template <typename T>
487     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>
493     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
515     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>
523     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>
530     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>
537     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
566     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>
574     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>
581     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>
588     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
619     explicit direct_assigner(const T& rhs) BOOST_NOEXCEPT
620         : rhs_(rhs)
621     {
622     }
623
624 public: // visitor interface
625
626     bool operator()(T& lhs)
627     {
628         lhs = rhs_;
629         return true;
630     }
631
632     template <typename 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
662     explicit direct_mover(T& rhs) BOOST_NOEXCEPT
663         : rhs_(rhs)
664     {
665     }
666
667 public: // visitor interface
668
669     bool operator()(T& lhs)
670     {
671         lhs = ::boost::detail::variant::move(rhs_);
672         return true;
673     }
674
675     template <typename 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>
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>
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>
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>
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>
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>
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
876     explicit swap_with(Variant& toswap) BOOST_NOEXCEPT
877         : toswap_(toswap)
878     {
879     }
880
881 public: // internal visitor interfaces
882
883     template <typename T>
884     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>
911     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
936     explicit comparer(const Variant& lhs) BOOST_NOEXCEPT
937         : lhs_(lhs)
938     {
939     }
940
941 public: // visitor interfaces
942
943     template <typename T>
944     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>
967     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>
981     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
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>
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<T>(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>
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(__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>
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>
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>
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>
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>
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>
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
1323     void indicate_which(int which_arg) BOOST_NOEXCEPT
1324     {
1325         which_ = static_cast<which_t>( which_arg );
1326     }
1327
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
1335     bool using_backup() const BOOST_NOEXCEPT
1336     {
1337         return which_ < 0;
1338     }
1339
1340 public: // queries
1341
1342     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
1362     void destroy_content() BOOST_NOEXCEPT
1363     {
1364         detail::variant::destroyer visitor;
1365         this->internal_apply_visitor(visitor);
1366     }
1367
1368 public: // structors
1369
1370     ~variant() BOOST_NOEXCEPT
1371     {
1372         destroy_content();
1373     }
1374
1375     variant() 
1376 #if !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130))
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
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>
1416         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(__BORLANDC__, BOOST_TESTED_AT(0x0564))
1427         template <typename T>
1428         result_type internal_visit(const T& operand, int) const
1429         {
1430             return initializer::initialize(storage_, operand);
1431         }
1432 #   endif
1433
1434         template <typename T>
1435         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>
1441         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>
1447         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>
1453         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>
1459         int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1460         {
1461             return internal_visit( operand.get(), 1L );
1462         }
1463
1464         template <typename T>
1465         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
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>
1492         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>
1503         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>
1509         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>
1515         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>
1521         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>
1527         int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1528         {
1529             return internal_visit( operand.get(), 1L );
1530         }
1531
1532         template <typename T>
1533         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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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_> > >::type* = 0)
1718     {
1719         convert_construct(operand, 1L);
1720     }
1721
1722     template <typename T>
1723     variant(
1724           T& operand
1725         , typename boost::enable_if<mpl::or_<
1726             mpl::and_<
1727                 mpl::not_< is_const<T> >,
1728                 mpl::not_< boost::is_same<T, variant> >,
1729                 boost::detail::variant::is_variant_constructible_from<T&, internal_types>
1730             >,
1731             boost::is_same<T, boost::recursive_variant_> > >::type* = 0
1732         )
1733     {
1734         convert_construct(operand, 1L);
1735     }
1736
1737 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1738     template <class T>
1739     variant(T&& operand,
1740         typename boost::enable_if<mpl::or_<
1741             mpl::and_<
1742                 boost::is_rvalue_reference<T&&>,
1743                 mpl::not_< boost::is_const<T> >,
1744                 mpl::not_< boost::is_same<T, variant> >,
1745                 boost::detail::variant::is_variant_constructible_from<T&&, internal_types>
1746             >,
1747             boost::is_same<T, boost::recursive_variant_> > >::type* = 0)
1748     {
1749         convert_construct( detail::variant::move(operand), 1L);
1750     }
1751 #endif
1752
1753 public: // structors, cont.
1754
1755     // [MSVC6 requires copy constructor appear after template constructors]
1756     variant(const variant& operand)
1757     {
1758         // Copy the value of operand into *this...
1759         detail::variant::copy_into visitor( storage_.address() );
1760         operand.internal_apply_visitor(visitor);
1761
1762         // ...and activate the *this's primary storage on success:
1763         indicate_which(operand.which());
1764     }
1765
1766 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1767     variant(variant&& operand) BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value)
1768     {
1769         // Move the value of operand into *this...
1770         detail::variant::move_into visitor( storage_.address() );
1771         operand.internal_apply_visitor(visitor);
1772
1773         // ...and activate the *this's primary storage on success:
1774         indicate_which(operand.which());
1775     }
1776 #endif
1777
1778 private: // helpers, for modifiers (below)
1779
1780 #   if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1781     template <typename Variant>
1782     friend class detail::variant::backup_assigner;
1783 #   endif
1784
1785     // class assigner
1786     //
1787     // Internal visitor that "assigns" the visited value to the given variant
1788     // by appropriate destruction and copy-construction.
1789     //
1790
1791     class assigner
1792         : public static_visitor<>
1793     {
1794     protected: // representation
1795
1796         variant& lhs_;
1797         const int rhs_which_;
1798
1799     public: // structors
1800
1801         assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
1802             : lhs_(lhs)
1803             , rhs_which_(rhs_which)
1804         {
1805         }
1806
1807     protected: // helpers, for internal visitor interface (below)
1808
1809         template <typename RhsT, typename B1, typename B2>
1810         void assign_impl(
1811               const RhsT& rhs_content
1812             , mpl::true_ // has_nothrow_copy
1813             , B1 // is_nothrow_move_constructible
1814             , B2 // has_fallback_type
1815             ) const BOOST_NOEXCEPT
1816         {
1817             // Destroy lhs's content...
1818             lhs_.destroy_content(); // nothrow
1819
1820             // ...copy rhs content into lhs's storage...
1821             new(lhs_.storage_.address())
1822                 RhsT( rhs_content ); // nothrow
1823
1824             // ...and indicate new content type:
1825             lhs_.indicate_which(rhs_which_); // nothrow
1826         }
1827
1828         template <typename RhsT, typename B>
1829         void assign_impl(
1830               const RhsT& rhs_content
1831             , mpl::false_ // has_nothrow_copy
1832             , mpl::true_ // is_nothrow_move_constructible
1833             , B // has_fallback_type
1834             ) const
1835         {
1836             // Attempt to make a temporary copy (so as to move it below)...
1837             RhsT temp(rhs_content);
1838
1839             // ...and upon success destroy lhs's content...
1840             lhs_.destroy_content(); // nothrow
1841
1842             // ...move the temporary copy into lhs's storage...
1843             new(lhs_.storage_.address())
1844                 RhsT( detail::variant::move(temp) ); // nothrow
1845
1846             // ...and indicate new content type:
1847             lhs_.indicate_which(rhs_which_); // nothrow
1848         }
1849
1850         void construct_fallback() const BOOST_NOEXCEPT {
1851             // In case of failure, default-construct fallback type in lhs's storage...
1852             new (lhs_.storage_.address())
1853                 fallback_type_; // nothrow
1854
1855             // ...indicate construction of fallback type...
1856             lhs_.indicate_which(
1857                   BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value
1858                 ); // nothrow
1859         }
1860
1861         template <typename RhsT>
1862         void assign_impl(
1863               const RhsT& rhs_content
1864             , mpl::false_ // has_nothrow_copy
1865             , mpl::false_ // is_nothrow_move_constructible
1866             , mpl::true_ // has_fallback_type
1867             ) const
1868         {
1869             // Destroy lhs's content...
1870             lhs_.destroy_content(); // nothrow
1871
1872             BOOST_TRY
1873             {
1874                 // ...and attempt to copy rhs's content into lhs's storage:
1875                 new(lhs_.storage_.address())
1876                     RhsT( rhs_content );
1877             }
1878             BOOST_CATCH (...)
1879             {
1880                 construct_fallback();
1881
1882                 // ...and rethrow:
1883                 BOOST_RETHROW;
1884             }
1885             BOOST_CATCH_END
1886
1887             // In the event of success, indicate new content type:
1888             lhs_.indicate_which(rhs_which_); // nothrow
1889         }
1890
1891         template <typename RhsT>
1892         void assign_impl(
1893               const RhsT& rhs_content
1894             , mpl::false_ // has_nothrow_copy
1895             , mpl::false_ // is_nothrow_move_constructible
1896             , mpl::false_ // has_fallback_type
1897             ) const
1898         {
1899             detail::variant::backup_assigner<wknd_self_t>
1900                 visitor(lhs_, rhs_which_, rhs_content);
1901             lhs_.internal_apply_visitor(visitor);
1902         }
1903
1904     public: // internal visitor interfaces
1905
1906         template <typename RhsT>
1907         void internal_visit(const RhsT& rhs_content, int) const
1908         {
1909             typedef typename has_nothrow_copy<RhsT>::type
1910                 nothrow_copy;
1911             typedef typename mpl::or_< // reduces compile-time
1912                   nothrow_copy
1913                 , is_nothrow_move_constructible<RhsT>
1914                 >::type nothrow_move_constructor;
1915
1916             assign_impl(
1917                   rhs_content
1918                 , nothrow_copy()
1919                 , nothrow_move_constructor()
1920                 , has_fallback_type_()
1921                 );
1922         }
1923
1924 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
1925     private:
1926         // silence MSVC warning C4512: assignment operator could not be generated
1927         assigner& operator= (assigner const&);
1928 #endif
1929     };
1930     
1931     friend class assigner;
1932    
1933 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1934     // class move_assigner
1935     //
1936     // Internal visitor that "move assigns" the visited value to the given variant
1937     // by appropriate destruction and move-construction.
1938     //
1939
1940     class move_assigner
1941         : public assigner
1942     {
1943     public: // structors
1944
1945         move_assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
1946             : assigner(lhs, rhs_which)
1947         {
1948         }
1949
1950     private: // helpers, for internal visitor interface (below)
1951         
1952         template <typename RhsT, typename B2>
1953         void assign_impl(
1954               RhsT& rhs_content
1955             , mpl::true_ // has_nothrow_copy
1956             , mpl::false_ // is_nothrow_move_constructible
1957             , B2 // has_fallback_type
1958             ) const BOOST_NOEXCEPT
1959         {
1960             assigner::assign_impl(rhs_content, mpl::true_(), mpl::false_(), B2());
1961         }
1962
1963         template <typename RhsT, typename B, typename B2>
1964         void assign_impl(
1965               RhsT& rhs_content
1966             , B // has_nothrow_copy
1967             , mpl::true_ // is_nothrow_move_constructible
1968             , B2 // has_fallback_type
1969             ) const BOOST_NOEXCEPT
1970         {
1971             // ...destroy lhs's content...
1972             assigner::lhs_.destroy_content(); // nothrow
1973
1974             // ...move the rhs_content into lhs's storage...
1975             new(assigner::lhs_.storage_.address())
1976                 RhsT( detail::variant::move(rhs_content) ); // nothrow
1977
1978             // ...and indicate new content type:
1979             assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
1980         }
1981
1982         template <typename RhsT>
1983         void assign_impl(
1984               RhsT& rhs_content
1985             , mpl::false_ // has_nothrow_copy
1986             , mpl::false_ // is_nothrow_move_constructible
1987             , mpl::true_ // has_fallback_type
1988             ) const
1989         {
1990             // Destroy lhs's content...
1991             assigner::lhs_.destroy_content(); // nothrow
1992
1993             BOOST_TRY
1994             {
1995                 // ...and attempt to copy rhs's content into lhs's storage:
1996                 new(assigner::lhs_.storage_.address())
1997                     RhsT( detail::variant::move(rhs_content) );
1998             }
1999             BOOST_CATCH (...)
2000             {
2001                 assigner::construct_fallback();
2002
2003                 // ...and rethrow:
2004                 BOOST_RETHROW;
2005             }
2006             BOOST_CATCH_END
2007
2008             // In the event of success, indicate new content type:
2009             assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
2010         }
2011         
2012         template <typename RhsT>
2013         void assign_impl(
2014               RhsT& rhs_content
2015             , mpl::false_ // has_nothrow_copy
2016             , mpl::false_ // is_nothrow_move_constructible
2017             , mpl::false_ // has_fallback_type
2018             ) const
2019         {
2020             assigner::assign_impl(rhs_content, mpl::false_(), mpl::false_(), mpl::false_());
2021         }
2022
2023     public: // internal visitor interfaces
2024
2025         template <typename RhsT>
2026         void internal_visit(RhsT& rhs_content, int) const
2027         {
2028             typedef typename is_nothrow_move_constructible<RhsT>::type
2029                 nothrow_move_constructor;
2030             typedef typename mpl::or_< // reduces compile-time
2031                   nothrow_move_constructor
2032                 , has_nothrow_copy<RhsT>
2033                 >::type nothrow_copy;
2034
2035             assign_impl(
2036                   rhs_content
2037                 , nothrow_copy()
2038                 , nothrow_move_constructor()
2039                 , has_fallback_type_()
2040                 );
2041         }
2042
2043 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
2044     private:
2045         // silence MSVC warning C4512: assignment operator could not be generated
2046         move_assigner& operator= (move_assigner const&);
2047 #endif
2048     };
2049
2050     friend class move_assigner;
2051 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2052
2053     void variant_assign(const variant& rhs)
2054     {
2055         // If the contained types are EXACTLY the same...
2056         if (which_ == rhs.which_)
2057         {
2058             // ...then assign rhs's storage to lhs's content:
2059             detail::variant::assign_storage visitor(rhs.storage_.address());
2060             this->internal_apply_visitor(visitor);
2061         }
2062         else
2063         {
2064             // Otherwise, perform general (copy-based) variant assignment:
2065             assigner visitor(*this, rhs.which());
2066             rhs.internal_apply_visitor(visitor); 
2067         }
2068     }
2069
2070 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2071     void variant_assign(variant&& rhs)
2072     {
2073         // If the contained types are EXACTLY the same...
2074         if (which_ == rhs.which_)
2075         {
2076             // ...then move rhs's storage to lhs's content:
2077             detail::variant::move_storage visitor(rhs.storage_.address());
2078             this->internal_apply_visitor(visitor);
2079         }
2080         else
2081         {
2082             // Otherwise, perform general (move-based) variant assignment:
2083             move_assigner visitor(*this, rhs.which());
2084             rhs.internal_apply_visitor(visitor); 
2085         }
2086     }
2087 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2088
2089 private: // helpers, for modifiers (below)
2090
2091     template <typename T>
2092     void assign(const T& rhs)
2093     {
2094         // If direct T-to-T assignment is not possible...
2095         detail::variant::direct_assigner<T> direct_assign(rhs);
2096         if (this->apply_visitor(direct_assign) == false)
2097         {
2098             // ...then convert rhs to variant and assign:
2099             //
2100             // While potentially inefficient, the following construction of a
2101             // variant allows T as any type convertible to one of the bounded
2102             // types without excessive code redundancy.
2103             //
2104             variant temp(rhs);
2105             variant_assign( detail::variant::move(temp) );
2106         }
2107     }
2108
2109 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2110     template <typename T>
2111     void move_assign(T&& rhs)
2112     {
2113         // If direct T-to-T move assignment is not possible...
2114         detail::variant::direct_mover<T> direct_move(rhs);
2115         if (this->apply_visitor(direct_move) == false)
2116         {
2117             // ...then convert rhs to variant and assign:
2118             //
2119             // While potentially inefficient, the following construction of a
2120             // variant allows T as any type convertible to one of the bounded
2121             // types without excessive code redundancy.
2122             //
2123             variant temp( detail::variant::move(rhs) );
2124             variant_assign( detail::variant::move(temp) );
2125         }
2126     }
2127 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2128
2129 public: // modifiers
2130
2131 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2132     template <class T>
2133     typename boost::enable_if<
2134         boost::mpl::and_<
2135             boost::is_rvalue_reference<T&&>,
2136             mpl::not_< boost::is_const<T> >,
2137             boost::detail::variant::is_variant_constructible_from<T&&, internal_types>
2138         >,
2139         variant&
2140     >::type operator=(T&& rhs) 
2141     {
2142         move_assign( detail::variant::move(rhs) );
2143         return *this;
2144     }
2145 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2146
2147     template <typename T>
2148     typename boost::enable_if<
2149         mpl::or_<
2150             boost::is_same<T, variant>,
2151             boost::detail::variant::is_variant_constructible_from<const T&, internal_types>
2152         >,
2153         variant&
2154     >::type operator=(const T& rhs)
2155     {
2156         assign(rhs);
2157         return *this;
2158     }
2159
2160     // [MSVC6 requires copy assign appear after templated operator=]
2161     variant& operator=(const variant& rhs)
2162     {
2163         variant_assign(rhs);
2164         return *this;
2165     }
2166
2167 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2168     variant& operator=(variant&& rhs) 
2169 #if !defined(__GNUC__) || (__GNUC__ != 4) || (__GNUC_MINOR__ > 6) || defined(__clang__)
2170         BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value && variant_move_noexcept_assignable::type::value)
2171 #endif
2172     {
2173         variant_assign( detail::variant::move(rhs) );
2174         return *this;
2175     }
2176 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2177
2178     void swap(variant& rhs)
2179     {
2180         // If the contained types are the same...
2181         if (which() == rhs.which())
2182         {
2183             // ...then swap the values directly:
2184             detail::variant::swap_with<variant> visitor(rhs);
2185             this->apply_visitor(visitor);
2186         }
2187         else
2188         {
2189             // ...otherwise, perform general variant swap:
2190             variant tmp( detail::variant::move(rhs) );
2191             rhs = detail::variant::move(*this);
2192             *this = detail::variant::move(tmp);
2193         }
2194     }
2195
2196 public: // queries
2197
2198     //
2199     // NOTE: member which() defined above.
2200     //
2201
2202     bool empty() const BOOST_NOEXCEPT
2203     {
2204         return false;
2205     }
2206
2207     const boost::typeindex::type_info& type() const
2208     {
2209         detail::variant::reflect visitor;
2210         return this->apply_visitor(visitor);
2211     }
2212
2213 public: // prevent comparison with foreign types
2214
2215     template <typename U>
2216     void operator==(const U&) const
2217     {
2218         BOOST_STATIC_ASSERT( false && sizeof(U) );
2219     }
2220
2221     template <typename U>
2222     void operator<(const U&) const
2223     {
2224         BOOST_STATIC_ASSERT( false && sizeof(U) );
2225     }
2226
2227     template <typename U>
2228     void operator!=(const U&) const
2229     {
2230         BOOST_STATIC_ASSERT( false && sizeof(U) );
2231     }
2232
2233     template <typename U>
2234     void operator>(const U&) const
2235     {
2236         BOOST_STATIC_ASSERT( false && sizeof(U) );
2237     }
2238
2239     template <typename U>
2240     void operator<=(const U&) const
2241     {
2242         BOOST_STATIC_ASSERT( false && sizeof(U) );
2243     }
2244
2245     template <typename U>
2246     void operator>=(const U&) const
2247     {
2248         BOOST_STATIC_ASSERT( false && sizeof(U) );
2249     }
2250
2251 public: // comparison operators
2252
2253     // [MSVC6 requires these operators appear after template operators]
2254
2255     bool operator==(const variant& rhs) const
2256     {
2257         if (this->which() != rhs.which())
2258             return false;
2259
2260         detail::variant::comparer<
2261               variant, detail::variant::equal_comp
2262             > visitor(*this);
2263         return rhs.apply_visitor(visitor);
2264     }
2265
2266     bool operator<(const variant& rhs) const
2267     {
2268         //
2269         // Dirk Schreib suggested this collating order.
2270         //
2271
2272         if (this->which() != rhs.which())
2273             return this->which() < rhs.which();
2274
2275         detail::variant::comparer<
2276               variant, detail::variant::less_comp
2277             > visitor(*this);
2278         return rhs.apply_visitor(visitor);
2279     }
2280
2281     ///////////////////////////////////////////////////////////////////////////////
2282     // comparison operators != > <= >=
2283     inline bool operator!=(const variant& rhs) const
2284     {
2285         return !(*this == rhs);
2286     }
2287
2288     inline bool operator>(const variant& rhs) const
2289     {
2290         return rhs < *this;
2291     }
2292
2293     inline bool operator<=(const variant& rhs) const
2294     {
2295         return !(*this > rhs);
2296     }
2297
2298     inline bool operator>=(const variant& rhs) const
2299     {
2300         return !(*this < rhs);
2301     }
2302
2303 // helpers, for visitation support (below) -- private when possible
2304 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2305
2306     template < BOOST_VARIANT_ENUM_PARAMS(typename U) >
2307     friend class variant;
2308
2309 private:
2310
2311 #else// defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2312
2313 public:
2314
2315 #endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2316
2317     template <typename Visitor, typename VoidPtrCV>
2318     BOOST_FORCEINLINE static typename Visitor::result_type
2319     internal_apply_visitor_impl(
2320           int internal_which
2321         , int logical_which
2322         , Visitor& visitor
2323         , VoidPtrCV storage
2324         )
2325     {
2326         typedef mpl::int_<0> first_which;
2327         typedef typename mpl::begin<internal_types>::type first_it;
2328         typedef typename mpl::end<internal_types>::type last_it;
2329
2330         typedef detail::variant::visitation_impl_step<
2331               first_it, last_it
2332             > first_step;
2333
2334         return detail::variant::visitation_impl(
2335               internal_which, logical_which
2336             , visitor, storage, mpl::false_()
2337             , never_uses_backup_flag()
2338             , static_cast<first_which*>(0), static_cast<first_step*>(0)
2339             );
2340     }
2341
2342     template <typename Visitor>
2343     BOOST_FORCEINLINE typename Visitor::result_type
2344     internal_apply_visitor(Visitor& visitor)
2345     {
2346         return internal_apply_visitor_impl(
2347               which_, which(), visitor, storage_.address()
2348             );
2349     }
2350
2351     template <typename Visitor>
2352     BOOST_FORCEINLINE typename Visitor::result_type
2353     internal_apply_visitor(Visitor& visitor) const
2354     {
2355         return internal_apply_visitor_impl(
2356               which_, which(), visitor, storage_.address()
2357             );
2358     }
2359
2360 public: // visitation support
2361
2362 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
2363
2364     template <typename Visitor>
2365     typename Visitor::result_type
2366     apply_visitor(Visitor& visitor) &&
2367     {
2368         detail::variant::invoke_visitor<Visitor, true> invoker(visitor);
2369         return this->internal_apply_visitor(invoker);
2370     }
2371
2372     template <typename Visitor>
2373     typename Visitor::result_type
2374     apply_visitor(Visitor& visitor) const&&
2375     {
2376         detail::variant::invoke_visitor<Visitor, true> invoker(visitor);
2377         return this->internal_apply_visitor(invoker);
2378     }
2379
2380 #endif
2381
2382     template <typename Visitor>
2383     typename Visitor::result_type
2384     apply_visitor(Visitor& visitor)
2385 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
2386     &
2387 #endif
2388     {
2389         detail::variant::invoke_visitor<Visitor, false> invoker(visitor);
2390         return this->internal_apply_visitor(invoker);
2391     }
2392
2393     template <typename Visitor>
2394     typename Visitor::result_type
2395     apply_visitor(Visitor& visitor) const
2396 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
2397     &
2398 #endif
2399     {
2400         detail::variant::invoke_visitor<Visitor, false> invoker(visitor);
2401         return this->internal_apply_visitor(invoker);
2402     }
2403
2404 }; // class variant
2405
2406 ///////////////////////////////////////////////////////////////////////////////
2407 // metafunction make_variant_over
2408 //
2409 // See docs and boost/variant/variant_fwd.hpp for more information.
2410 //
2411 template <typename Types>
2412 struct make_variant_over
2413 {
2414 private: // precondition assertions
2415
2416     BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value ));
2417     typedef typename boost::mpl::insert_range<
2418       boost::mpl::list<>
2419     , boost::mpl::end< boost::mpl::list<> >::type
2420     , Types
2421     >::type copied_sequence_t;
2422
2423 public: // metafunction result
2424
2425     typedef variant<
2426           detail::variant::over_sequence<copied_sequence_t>
2427         > type;
2428
2429 };
2430
2431 ///////////////////////////////////////////////////////////////////////////////
2432 // function template swap
2433 //
2434 // Swaps two variants of the same type (i.e., identical specification).
2435 //
2436 template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
2437 inline void swap(
2438       variant< BOOST_VARIANT_ENUM_PARAMS(T) >& lhs
2439     , variant< BOOST_VARIANT_ENUM_PARAMS(T) >& rhs
2440     )
2441 {
2442     lhs.swap(rhs);
2443 }
2444
2445 } // namespace boost
2446
2447 // implementation additions
2448
2449 #if !defined(BOOST_NO_IOSTREAM)
2450 #include <boost/variant/detail/variant_io.hpp>
2451 #endif // BOOST_NO_IOSTREAM
2452
2453 #endif // BOOST_VARIANT_VARIANT_HPP