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

source code of boost/boost/variant/variant.hpp