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