1 //-----------------------------------------------------------------------------
2 // boost variant/variant.hpp header file
3 // See http://www.boost.org for updates, documentation, and revision history.
4 //-----------------------------------------------------------------------------
6 // Copyright (c) 2002-2003 Eric Friedman, Itay Maman
7 // Copyright (c) 2012-2016 Antony Polukhin
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)
13 // Thanks to Adam Romanek for providing patches for exception-disabled env.
15 #ifndef BOOST_VARIANT_VARIANT_HPP
16 #define BOOST_VARIANT_VARIANT_HPP
18 #include <cstddef> // for std::size_t
19 #include <new> // for placement new
21 #include <boost/type_index.hpp>
23 #include <boost/variant/detail/config.hpp>
24 #include <boost/mpl/aux_/value_wknd.hpp>
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>
36 #include <boost/variant/detail/generic_result_type.hpp>
37 #include <boost/variant/detail/move.hpp>
39 #include <boost/detail/no_exceptions_support.hpp>
40 #include <boost/detail/reference_content.hpp>
41 #include <boost/aligned_storage.hpp>
42 #include <boost/blank.hpp>
43 #include <boost/math/common_factor_ct.hpp>
44 #include <boost/static_assert.hpp>
45 #include <boost/preprocessor/cat.hpp>
46 #include <boost/preprocessor/repeat.hpp>
47 #include <boost/type_traits/alignment_of.hpp>
48 #include <boost/type_traits/add_const.hpp>
49 #include <boost/type_traits/has_nothrow_constructor.hpp>
50 #include <boost/type_traits/has_nothrow_copy.hpp>
51 #include <boost/type_traits/is_nothrow_move_assignable.hpp>
52 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
53 #include <boost/type_traits/is_const.hpp>
54 #include <boost/type_traits/is_same.hpp>
55 #include <boost/type_traits/is_rvalue_reference.hpp>
56 #include <boost/type_traits/is_constructible.hpp>
57 #include <boost/type_traits/add_lvalue_reference.hpp>
58 #include <boost/utility/enable_if.hpp>
59 #include <boost/utility/declval.hpp>
60 #include <boost/variant/recursive_wrapper_fwd.hpp>
61 #include <boost/variant/static_visitor.hpp>
63 #include <boost/mpl/assert.hpp>
64 #include <boost/mpl/begin_end.hpp>
65 #include <boost/mpl/bool.hpp>
66 #include <boost/mpl/deref.hpp>
67 #include <boost/mpl/empty.hpp>
68 #include <boost/mpl/eval_if.hpp>
69 #include <boost/mpl/find_if.hpp>
70 #include <boost/mpl/fold.hpp>
71 #include <boost/mpl/front.hpp>
72 #include <boost/mpl/identity.hpp>
73 #include <boost/mpl/if.hpp>
74 #include <boost/mpl/int.hpp>
75 #include <boost/mpl/is_sequence.hpp>
76 #include <boost/mpl/iterator_range.hpp>
77 #include <boost/mpl/iter_fold_if.hpp>
78 #include <boost/mpl/logical.hpp>
79 #include <boost/mpl/max_element.hpp>
80 #include <boost/mpl/next.hpp>
81 #include <boost/mpl/not.hpp>
82 #include <boost/mpl/pair.hpp>
83 #include <boost/mpl/protect.hpp>
84 #include <boost/mpl/push_front.hpp>
85 #include <boost/mpl/same_as.hpp>
86 #include <boost/mpl/size_t.hpp>
87 #include <boost/mpl/sizeof.hpp>
88 #include <boost/mpl/transform.hpp>
90 ///////////////////////////////////////////////////////////////////////////////
91 // Implementation Macros:
93 // BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
94 // Defined in boost/variant/detail/visitation_impl.hpp.
96 // BOOST_VARIANT_MINIMIZE_SIZE
97 // When #defined, implementation employs all known means to minimize the
98 // size of variant obje cts. However, often unsuccessful due to alignment
99 // issues, and potentially harmful to runtime speed, so not enabled by
100 // default. (TODO: Investigate further.)
102 #if defined(BOOST_VARIANT_MINIMIZE_SIZE)
103 # include <climits> // for SCHAR_MAX
104 # include <boost/mpl/eval_if.hpp>
105 # include <boost/mpl/equal_to.hpp>
106 # include <boost/mpl/identity.hpp>
107 # include <boost/mpl/int.hpp>
108 # include <boost/mpl/if.hpp>
109 # include <boost/mpl/less.hpp>
110 # include <boost/mpl/long.hpp>
111 # include <boost/mpl/O1_size.hpp>
117 namespace detail { namespace variant {
119 ///////////////////////////////////////////////////////////////////////////////
120 // (detail) metafunction max_value
122 // Finds the maximum value of the unary metafunction F over Sequence.
124 template <typename Sequence, typename F>
127 private: // helpers, for metafunction result (below)
129 typedef typename mpl::transform1<Sequence, F>::type transformed_;
130 typedef typename mpl::max_element<transformed_
134 public: // metafunction result
136 typedef typename mpl::deref<max_it>::type
143 template <typename State, typename Item>
146 ::boost::math::static_lcm<
147 BOOST_MPL_AUX_VALUE_WKND(State)::value
148 , ::boost::alignment_of<Item>::value
154 ///////////////////////////////////////////////////////////////////////////////
155 // (detail) metafunction find_fallback_type
157 // Provides a fallback (i.e., nothrow default-constructible) type from the
158 // specified sequence, or no_fallback_type if not found.
160 // This implementation is designed to prefer boost::blank over other potential
161 // fallback types, regardless of its position in the specified sequence.
164 class no_fallback_type;
166 struct find_fallback_type_pred
168 template <typename Iterator>
172 typedef typename mpl::deref<Iterator>::type t_;
175 typedef mpl::not_< has_nothrow_constructor<t_> > type;
179 template <typename Types>
180 struct find_fallback_type
182 private: // helpers, for metafunction result (below)
184 typedef typename mpl::end<Types>::type end_it;
186 // [Find the first suitable fallback type...]
188 typedef typename mpl::iter_fold_if<
190 , mpl::int_<0>, mpl::protect< mpl::next<> >
191 , mpl::protect< find_fallback_type_pred >
192 >::type first_result_;
194 typedef typename first_result_::first first_result_index;
195 typedef typename first_result_::second first_result_it;
197 // [...now search the rest of the sequence for boost::blank...]
199 typedef typename mpl::iter_fold_if<
200 mpl::iterator_range< first_result_it,end_it >
201 , first_result_index, mpl::protect< mpl::next<> >
202 , mpl::protect< mpl::not_same_as<boost::blank> >
203 >::type second_result_;
205 typedef typename second_result_::second second_result_it;
207 public: // metafunction result
209 // [...and return the results of the search:]
210 typedef typename mpl::eval_if<
211 is_same< second_result_it,end_it >
213 is_same< first_result_it,end_it >
214 , mpl::pair< no_fallback_type,no_fallback_type >
217 , mpl::identity< second_result_ >
222 #ifndef BOOST_NO_CXX11_NOEXCEPT
223 ///////////////////////////////////////////////////////////////////////////////
224 // (detail) metafunction is_variant_move_noexcept_constructible
226 // Returns true_type if all the types are nothrow move constructible.
228 template <class Types>
229 struct is_variant_move_noexcept_constructible {
230 typedef typename boost::mpl::find_if<
231 Types, mpl::not_<boost::is_nothrow_move_constructible<boost::mpl::_1> >
234 typedef typename boost::mpl::end<Types>::type end_t;
235 typedef typename boost::is_same<
240 ///////////////////////////////////////////////////////////////////////////////
241 // (detail) metafunction is_variant_move_noexcept_assignable
243 // Returns true_type if all the types are nothrow move constructible.
245 template <class Types>
246 struct is_variant_move_noexcept_assignable {
247 typedef typename boost::mpl::find_if<
248 Types, mpl::not_<boost::is_nothrow_move_assignable<boost::mpl::_1> >
251 typedef typename boost::mpl::end<Types>::type end_t;
252 typedef typename boost::is_same<
256 #endif // BOOST_NO_CXX11_NOEXCEPT
258 ///////////////////////////////////////////////////////////////////////////////
259 // (detail) metafunction is_variant_constructible_from
261 // Derives from true_type if at least one variant's type is constructible from T.
263 template <class T1, class T2>
264 struct is_constructible_ext:
266 boost::is_constructible<
270 boost::is_constructible<
272 typename boost::add_lvalue_reference<T2>::type
277 template <class T, class Types>
278 struct is_variant_constructible_from:
279 boost::mpl::not_< boost::is_same<
280 typename boost::mpl::find_if<
282 is_constructible_ext<boost::mpl::_1, T>
284 typename boost::mpl::end<Types>::type
288 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
289 struct is_variant_constructible_from< boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >:
291 typename boost::mpl::find_if<
292 typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::recursive_enabled_types,
293 mpl::not_< is_variant_constructible_from< boost::mpl::_1, Types> >
295 typename boost::mpl::end< typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::recursive_enabled_types >::type
299 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
300 struct is_variant_constructible_from< const boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& , Types >:
301 is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >
304 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
305 struct is_variant_constructible_from< boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& , Types >:
306 is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >
309 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
311 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
312 struct is_variant_constructible_from< boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>&& , Types >:
313 is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >
316 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
317 struct is_variant_constructible_from< boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const && , Types >:
318 is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >
321 #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCE
324 ///////////////////////////////////////////////////////////////////////////////
325 // (detail) metafunction make_storage
327 // Provides an aligned storage type capable of holding any of the types
328 // specified in the given type-sequence.
331 template <typename Types, typename NeverUsesBackupFlag>
334 private: // helpers, for metafunction result (below)
336 typedef typename mpl::eval_if<
338 , mpl::identity< Types >
340 Types, backup_holder<void*>
344 typedef typename max_value<
345 types, mpl::sizeof_<mpl::_1>
348 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
350 typedef typename mpl::fold<
354 >::type max_alignment;
358 // temporary workaround -- use maximal alignment
359 typedef mpl::size_t< -1 > max_alignment;
361 #endif // borland workaround
363 public: // metafunction result
365 typedef ::boost::aligned_storage<
366 BOOST_MPL_AUX_VALUE_WKND(max_size)::value
367 , BOOST_MPL_AUX_VALUE_WKND(max_alignment)::value
371 ///////////////////////////////////////////////////////////////////////////////
372 // (detail) class destroyer
374 // Internal visitor that destroys the value it visits.
377 : public static_visitor<>
379 public: // visitor interfaces
381 template <typename T>
382 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
383 internal_visit(T& operand, int) const BOOST_NOEXCEPT
385 operand.~T(); // must be noexcept
387 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551)) || \
388 BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
389 operand; // suppresses warnings
392 BOOST_VARIANT_AUX_RETURN_VOID;
397 ///////////////////////////////////////////////////////////////////////////////
398 // (detail) class template known_get
400 // Visitor that returns a reference to content of the specified type.
402 // Precondition: visited variant MUST contain logical content of type T.
404 template <typename T>
406 : public static_visitor<T&>
409 public: // visitor interface
411 T& operator()(T& operand) const BOOST_NOEXCEPT
416 template <typename U>
417 T& operator()(U&) const
419 // logical error to be here: see precondition above
420 return ::boost::detail::variant::forced_return< T& >();
424 ///////////////////////////////////////////////////////////////////////////////
425 // (detail) class copy_into
427 // Internal visitor that copies the value it visits into the given buffer.
430 : public static_visitor<>
432 private: // representation
438 explicit copy_into(void* storage) BOOST_NOEXCEPT
443 public: // internal visitor interface
445 template <typename T>
446 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
447 internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
449 new(storage_) T( operand.get() );
450 BOOST_VARIANT_AUX_RETURN_VOID;
453 template <typename T>
454 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
455 internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
457 new(storage_) T( operand.get() );
458 BOOST_VARIANT_AUX_RETURN_VOID;
461 template <typename T>
462 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
463 internal_visit(const T& operand, int) const
465 new(storage_) T(operand);
466 BOOST_VARIANT_AUX_RETURN_VOID;
471 ///////////////////////////////////////////////////////////////////////////////
472 // (detail) class move_into
474 // Internal visitor that moves the value it visits into the given buffer.
476 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
478 : public static_visitor<>
480 private: // representation
486 explicit move_into(void* storage) BOOST_NOEXCEPT
491 public: // internal visitor interface
493 template <typename T>
494 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
495 internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
497 new(storage_) T( ::boost::detail::variant::move(operand.get()) );
498 BOOST_VARIANT_AUX_RETURN_VOID;
501 template <typename T>
502 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
503 internal_visit(T& operand, int) const BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(boost::declval<T>())))
505 new(storage_) T(::boost::detail::variant::move(operand));
506 BOOST_VARIANT_AUX_RETURN_VOID;
511 ///////////////////////////////////////////////////////////////////////////////
512 // (detail) class assign_storage
514 // Internal visitor that assigns the given storage (which must be a
515 // constructed value of the same type) to the value it visits.
517 struct assign_storage
518 : public static_visitor<>
520 private: // representation
522 const void* rhs_storage_;
526 explicit assign_storage(const void* rhs_storage) BOOST_NOEXCEPT
527 : rhs_storage_(rhs_storage)
531 public: // internal visitor interfaces
533 template <typename T>
534 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
535 internal_visit(backup_holder<T>& lhs_content, long) const
538 = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
539 BOOST_VARIANT_AUX_RETURN_VOID;
542 template <typename T>
543 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
544 internal_visit(const backup_holder<T>& lhs_content, long) const
547 = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
548 BOOST_VARIANT_AUX_RETURN_VOID;
551 template <typename T>
552 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
553 internal_visit(T& lhs_content, int) const
556 // Compile error here indicates one of variant's bounded types does
557 // not meet the requirements of the Assignable concept. Thus,
558 // variant is not Assignable.
560 // Hint: Are any of the bounded types const-qualified or references?
562 lhs_content = *static_cast< const T* >(rhs_storage_);
563 BOOST_VARIANT_AUX_RETURN_VOID;
568 ///////////////////////////////////////////////////////////////////////////////
569 // (detail) class move_storage
571 // Internal visitor that moves the given storage (which must be a
572 // constructed value of the same type) to the value it visits.
575 : public static_visitor<>
577 private: // representation
583 explicit move_storage(void* rhs_storage) BOOST_NOEXCEPT
584 : rhs_storage_(rhs_storage)
588 public: // internal visitor interfaces
590 template <typename T>
591 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
592 internal_visit(backup_holder<T>& lhs_content, long) const
595 = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
596 BOOST_VARIANT_AUX_RETURN_VOID;
599 template <typename T>
600 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
601 internal_visit(const backup_holder<T>& lhs_content, long) const
604 = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
605 BOOST_VARIANT_AUX_RETURN_VOID;
608 template <typename T>
609 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
610 internal_visit(T& lhs_content, int) const
613 // Compile error here indicates one of variant's bounded types does
614 // not meet the requirements of the Assignable concept. Thus,
615 // variant is not Assignable.
617 // Hint: Are any of the bounded types const-qualified or references?
619 lhs_content = ::boost::detail::variant::move(*static_cast<T* >(rhs_storage_));
620 BOOST_VARIANT_AUX_RETURN_VOID;
625 ///////////////////////////////////////////////////////////////////////////////
626 // (detail) class direct_assigner
628 // Generic static visitor that: if and only if the visited value is of the
629 // specified type, assigns the given value to the visited value and returns
630 // true; else returns false.
632 template <typename T>
633 class direct_assigner
634 : public static_visitor<bool>
636 private: // representation
642 explicit direct_assigner(const T& rhs) BOOST_NOEXCEPT
647 public: // visitor interface
649 bool operator()(T& lhs)
655 template <typename U>
656 bool operator()(U&) BOOST_NOEXCEPT
661 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
663 // silence MSVC warning C4512: assignment operator could not be generated
664 direct_assigner& operator= (direct_assigner const&);
668 ///////////////////////////////////////////////////////////////////////////////
669 // (detail) class direct_mover
671 // Generic static visitor that: if and only if the visited value is of the
672 // specified type, move assigns the given value to the visited value and returns
673 // true; else returns false.
675 template <typename T>
677 : public static_visitor<bool>
679 private: // representation
685 explicit direct_mover(T& rhs) BOOST_NOEXCEPT
690 public: // visitor interface
692 bool operator()(T& lhs)
694 lhs = ::boost::detail::variant::move(rhs_);
698 template <typename U>
699 bool operator()(U&) BOOST_NOEXCEPT
704 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
706 // silence MSVC warning C4512: assignment operator could not be generated
707 direct_mover& operator= (direct_mover const&);
712 ///////////////////////////////////////////////////////////////////////////////
713 // (detail) class backup_assigner
715 // Internal visitor that "assigns" the given value to the visited value,
716 // using backup to recover if the destroy-copy sequence fails.
718 // NOTE: This needs to be a friend of variant, as it needs access to
719 // indicate_which, indicate_backup_which, etc.
721 template <typename Variant>
722 class backup_assigner
723 : public static_visitor<>
725 private: // representation
729 const void* rhs_content_;
730 void (*copy_rhs_content_)(void*, const void*);
735 backup_assigner(Variant& lhs, int rhs_which, const RhsT& rhs_content)
737 , rhs_which_(rhs_which)
738 , rhs_content_(&rhs_content)
739 , copy_rhs_content_(&construct_impl<RhsT>)
743 private: // helpers, for visitor interface (below)
746 static void construct_impl(void* addr, const void* obj)
748 new(addr) RhsT(*static_cast<const RhsT*>(obj));
751 template <typename LhsT>
752 void backup_assign_impl(
753 backup_holder<LhsT>& lhs_content
754 , mpl::false_ // is_nothrow_move_constructible
758 // Move lhs content to backup...
759 backup_holder<LhsT> backup_lhs_content(0);
760 backup_lhs_content.swap(lhs_content); // nothrow
762 // ...destroy lhs content...
763 lhs_content.~backup_holder<LhsT>(); // nothrow
767 // ...and attempt to copy rhs content into lhs storage:
768 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
772 // In case of failure, copy backup pointer to lhs storage...
773 new(lhs_.storage_.address())
774 backup_holder<LhsT>( 0 ); // nothrow
776 static_cast<backup_holder<LhsT>* >(lhs_.storage_.address())
777 ->swap(backup_lhs_content); // nothrow
784 // In case of success, indicate new content type:
785 lhs_.indicate_which(rhs_which_); // nothrow
788 template <typename LhsT>
789 void backup_assign_impl(
791 , mpl::true_ // is_nothrow_move_constructible
795 // Move lhs content to backup...
796 LhsT backup_lhs_content(
797 ::boost::detail::variant::move(lhs_content)
800 // ...destroy lhs content...
801 lhs_content.~LhsT(); // nothrow
805 // ...and attempt to copy rhs content into lhs storage:
806 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
810 // In case of failure, restore backup content to lhs storage...
811 new(lhs_.storage_.address())
813 ::boost::detail::variant::move(backup_lhs_content)
821 // In case of success, indicate new content type:
822 lhs_.indicate_which(rhs_which_); // nothrow
825 template <typename LhsT>
826 void backup_assign_impl(
828 , mpl::false_ // is_nothrow_move_constructible
832 // Backup lhs content...
833 LhsT* backup_lhs_ptr = new LhsT(lhs_content);
835 // ...destroy lhs content...
836 lhs_content.~LhsT(); // nothrow
840 // ...and attempt to copy rhs content into lhs storage:
841 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
845 // In case of failure, copy backup pointer to lhs storage...
846 new(lhs_.storage_.address())
847 backup_holder<LhsT>( backup_lhs_ptr ); // nothrow
849 // ...indicate now using backup...
850 lhs_.indicate_backup_which( lhs_.which() ); // nothrow
857 // In case of success, indicate new content type...
858 lhs_.indicate_which(rhs_which_); // nothrow
860 // ...and delete backup:
861 delete backup_lhs_ptr; // nothrow
864 public: // visitor interface
866 template <typename LhsT>
867 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
868 internal_visit(LhsT& lhs_content, int)
870 typedef typename is_nothrow_move_constructible<LhsT>::type
873 backup_assign_impl( lhs_content, nothrow_move(), 1L);
875 BOOST_VARIANT_AUX_RETURN_VOID;
878 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
880 // silence MSVC warning C4512: assignment operator could not be generated
881 backup_assigner& operator= (backup_assigner const&);
885 ///////////////////////////////////////////////////////////////////////////////
886 // (detail) class swap_with
888 // Visitor that swaps visited value with content of given variant.
890 // Precondition: Given variant MUST have same logical type as visited value.
892 template <typename Variant>
894 : public static_visitor<>
896 private: // representation
902 explicit swap_with(Variant& toswap) BOOST_NOEXCEPT
907 public: // internal visitor interfaces
909 template <typename T>
910 void operator()(T& operand) const
912 // Since the precondition ensures types are same, get T...
914 T& other = toswap_.apply_visitor(getter);
917 ::boost::detail::variant::move_swap( operand, other );
921 swap_with& operator=(const swap_with&);
925 ///////////////////////////////////////////////////////////////////////////////
926 // (detail) class reflect
928 // Generic static visitor that performs a typeid on the value it visits.
932 : public static_visitor<const boost::typeindex::type_info&>
934 public: // visitor interfaces
936 template <typename T>
937 const boost::typeindex::type_info& operator()(const T&) const BOOST_NOEXCEPT
939 return boost::typeindex::type_id<T>().type_info();
944 ///////////////////////////////////////////////////////////////////////////////
945 // (detail) class comparer
947 // Generic static visitor that compares the content of the given lhs variant
948 // with the visited rhs content using Comp.
950 // Precondition: lhs.which() == rhs.which()
952 template <typename Variant, typename Comp>
954 : public static_visitor<bool>
956 private: // representation
962 explicit comparer(const Variant& lhs) BOOST_NOEXCEPT
967 public: // visitor interfaces
969 template <typename T>
970 bool operator()(T& rhs_content) const
972 // Since the precondition ensures lhs and rhs types are same, get T...
974 const T& lhs_content = lhs_.apply_visitor(getter);
976 // ...and compare lhs and rhs contents:
977 return Comp()(lhs_content, rhs_content);
981 comparer& operator=(const comparer&);
985 ///////////////////////////////////////////////////////////////////////////////
986 // (detail) class equal_comp
988 // Generic function object compares lhs with rhs using operator==.
992 template <typename T>
993 bool operator()(const T& lhs, const T& rhs) const
999 ///////////////////////////////////////////////////////////////////////////////
1000 // (detail) class less_comp
1002 // Generic function object compares lhs with rhs using operator<.
1006 template <typename T>
1007 bool operator()(const T& lhs, const T& rhs) const
1013 ///////////////////////////////////////////////////////////////////////////////
1014 // (detail) class template invoke_visitor
1016 // Internal visitor that invokes the given visitor using:
1017 // * for wrappers (e.g., recursive_wrapper), the wrapper's held value.
1018 // * for all other values, the value itself.
1020 template <typename Visitor>
1021 class invoke_visitor
1023 private: // representation
1027 public: // visitor typedefs
1029 typedef typename Visitor::result_type
1032 public: // structors
1034 explicit invoke_visitor(Visitor& visitor) BOOST_NOEXCEPT
1039 #if !defined(BOOST_NO_VOID_RETURNS)
1041 public: // internal visitor interfaces
1043 template <typename T>
1044 result_type internal_visit(T& operand, int)
1046 return visitor_(operand);
1049 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
1050 template <typename T>
1051 result_type internal_visit(const T& operand, int)
1053 return visitor_(operand);
1057 #else // defined(BOOST_NO_VOID_RETURNS)
1059 private: // helpers, for internal visitor interfaces (below)
1061 template <typename T>
1062 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1063 visit_impl(T& operand, mpl::false_)
1065 return visitor_(operand);
1068 template <typename T>
1069 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
1070 visit_impl(T& operand, mpl::true_)
1073 BOOST_VARIANT_AUX_RETURN_VOID;
1076 public: // internal visitor interfaces
1078 template <typename T>
1079 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1080 internal_visit(T& operand, int)
1082 typedef typename is_same<result_type, void>::type
1083 has_void_result_type;
1085 return visit_impl(operand, has_void_result_type());
1088 #endif // BOOST_NO_VOID_RETURNS) workaround
1090 public: // internal visitor interfaces, cont.
1092 template <typename T>
1093 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1094 internal_visit(boost::recursive_wrapper<T>& operand, long)
1096 return internal_visit( operand.get(), 1L );
1099 template <typename T>
1100 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1101 internal_visit(const boost::recursive_wrapper<T>& operand, long)
1103 return internal_visit( operand.get(), 1L );
1106 template <typename T>
1107 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1108 internal_visit(boost::detail::reference_content<T>& operand, long)
1110 return internal_visit( operand.get(), 1L );
1113 template <typename T>
1114 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1115 internal_visit(const boost::detail::reference_content<T>& operand, long)
1117 return internal_visit( operand.get(), 1L );
1120 template <typename T>
1121 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1122 internal_visit(boost::detail::variant::backup_holder<T>& operand, long)
1124 return internal_visit( operand.get(), 1L );
1127 template <typename T>
1128 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1129 internal_visit(const boost::detail::variant::backup_holder<T>& operand, long)
1131 return internal_visit( operand.get(), 1L );
1134 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
1136 // silence MSVC warning C4512: assignment operator could not be generated
1137 invoke_visitor& operator= (invoke_visitor const&);
1141 }} // namespace detail::variant
1143 ///////////////////////////////////////////////////////////////////////////////
1144 // class template variant (concept inspired by Andrei Alexandrescu)
1146 // See docs and boost/variant/variant_fwd.hpp for more information.
1150 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)
1154 private: // helpers, for typedefs (below)
1156 typedef variant wknd_self_t;
1158 struct is_recursive_
1159 : detail::variant::is_recursive_flag<T0_>
1163 typedef typename mpl::eval_if<
1166 , mpl::identity< T0_ >
1167 >::type unwrapped_T0_;
1169 struct is_sequence_based_
1170 : detail::variant::is_over_sequence<unwrapped_T0_>
1174 #if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
1176 private: // helpers, for typedefs (below)
1178 typedef typename mpl::eval_if<
1180 , unwrapped_T0_ // over_sequence<...>::type
1181 , detail::variant::make_variant_list<
1183 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
1185 >::type specified_types;
1187 BOOST_STATIC_ASSERT((
1188 ::boost::mpl::not_< mpl::empty<specified_types> >::value
1191 public: // public typedefs
1192 typedef typename mpl::eval_if<
1197 detail::variant::quoted_enable_recursive<wknd_self_t>
1200 , mpl::identity< specified_types >
1201 >::type recursive_enabled_types; // used by is_variant_constructible_from<> trait
1203 typedef typename mpl::transform<
1204 recursive_enabled_types
1205 , unwrap_recursive<mpl::_1>
1208 private: // internal typedefs
1210 typedef typename mpl::transform<
1211 recursive_enabled_types
1212 , mpl::protect< detail::make_reference_content<> >
1213 >::type internal_types;
1215 typedef typename mpl::front<
1217 >::type internal_T0;
1219 #else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
1221 private: // helpers, for typedefs (below)
1223 typedef unwrapped_T0_ T0;
1225 #define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
1226 typedef typename mpl::eval_if< \
1228 , detail::variant::enable_recursive< \
1232 , mpl::identity< BOOST_PP_CAT(T,N) > \
1233 >::type BOOST_PP_CAT(recursive_enabled_T,N); \
1237 BOOST_VARIANT_LIMIT_TYPES
1238 , BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1242 #undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1244 #define BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS(z,N,_) \
1245 typedef typename unwrap_recursive< \
1246 BOOST_PP_CAT(recursive_enabled_T,N) \
1247 >::type BOOST_PP_CAT(public_T,N); \
1251 BOOST_VARIANT_LIMIT_TYPES
1252 , BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1256 #undef BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1258 public: // public typedefs
1260 typedef typename detail::variant::make_variant_list<
1261 BOOST_VARIANT_ENUM_PARAMS(public_T)
1264 private: // helpers, for internal typedefs (below)
1266 #define BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS(z,N,_) \
1267 typedef detail::make_reference_content< \
1268 BOOST_PP_CAT(recursive_enabled_T,N) \
1269 >::type BOOST_PP_CAT(internal_T,N); \
1273 BOOST_VARIANT_LIMIT_TYPES
1274 , BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1278 #undef BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1280 private: // internal typedefs
1282 typedef typename detail::variant::make_variant_list<
1283 BOOST_VARIANT_ENUM_PARAMS(internal_T)
1284 >::type internal_types;
1286 private: // static precondition assertions
1289 // variant< type-sequence > syntax is not supported on this compiler!
1291 BOOST_MPL_ASSERT_NOT(( is_sequence_based_ ));
1293 #endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT workaround
1295 private: // helpers, for representation (below)
1297 typedef typename detail::variant::find_fallback_type<
1299 >::type fallback_type_result_;
1301 typedef typename fallback_type_result_::first
1302 fallback_type_index_;
1303 typedef typename fallback_type_result_::second
1306 struct has_fallback_type_
1308 is_same< fallback_type_, detail::variant::no_fallback_type >
1313 typedef has_fallback_type_
1314 never_uses_backup_flag;
1316 typedef typename detail::variant::make_storage<
1317 internal_types, never_uses_backup_flag
1320 #ifndef BOOST_NO_CXX11_NOEXCEPT
1321 typedef typename detail::variant::is_variant_move_noexcept_constructible<
1323 > variant_move_noexcept_constructible;
1325 typedef typename detail::variant::is_variant_move_noexcept_assignable<
1327 > variant_move_noexcept_assignable;
1331 private: // helpers, for representation (below)
1334 // * [0, size<internal_types>) indicates stack content
1335 // * [-size<internal_types>, 0) indicates pointer to heap backup
1337 // * then which() -> which_
1338 // * else which() -> -(which_ + 1)
1340 #if !defined(BOOST_VARIANT_MINIMIZE_SIZE)
1342 typedef int which_t;
1344 #else // defined(BOOST_VARIANT_MINIMIZE_SIZE)
1346 // [if O1_size available, then attempt which_t size optimization...]
1347 // [select signed char if fewer than SCHAR_MAX types, else signed int:]
1348 typedef typename mpl::eval_if<
1349 mpl::equal_to< mpl::O1_size<internal_types>, mpl::long_<-1> >
1350 , mpl::identity< int >
1352 mpl::less< mpl::O1_size<internal_types>, mpl::int_<SCHAR_MAX> >
1358 #endif // BOOST_VARIANT_MINIMIZE_SIZE switch
1360 // representation -- private when possible
1361 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1370 void indicate_which(int which_arg) BOOST_NOEXCEPT
1372 which_ = static_cast<which_t>( which_arg );
1375 void indicate_backup_which(int which_arg) BOOST_NOEXCEPT
1377 which_ = static_cast<which_t>( -(which_arg + 1) );
1380 private: // helpers, for queries (below)
1382 bool using_backup() const BOOST_NOEXCEPT
1389 int which() const BOOST_NOEXCEPT
1391 // If using heap backup...
1393 // ...then return adjusted which_:
1394 return -(which_ + 1);
1396 // Otherwise, return which_ directly:
1400 private: // helpers, for structors (below)
1403 : BOOST_VARIANT_AUX_INITIALIZER_T(
1404 recursive_enabled_types, recursive_enabled_T
1409 void destroy_content() BOOST_NOEXCEPT
1411 detail::variant::destroyer visitor;
1412 this->internal_apply_visitor(visitor);
1415 public: // structors
1417 ~variant() BOOST_NOEXCEPT
1423 #if !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130))
1424 BOOST_NOEXCEPT_IF(boost::has_nothrow_constructor<internal_T0>::value)
1428 #pragma warning( push )
1429 // behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized
1430 #pragma warning( disable : 4345 )
1433 // Compile error from here indicates that the first bound
1434 // type is not default-constructible, and so variant cannot
1435 // support its own default-construction.
1437 new( storage_.address() ) internal_T0();
1438 indicate_which(0); // zero is the index of the first bounded type
1440 #pragma warning( pop )
1444 private: // helpers, for structors, cont. (below)
1446 class convert_copy_into
1447 : public static_visitor<int>
1449 private: // representation
1453 public: // structors
1455 explicit convert_copy_into(void* storage) BOOST_NOEXCEPT
1460 public: // internal visitor interfaces (below)
1462 template <typename T>
1463 int internal_visit(T& operand, int) const
1466 // Compile error here indicates one of the source variant's types
1467 // cannot be unambiguously converted to the destination variant's
1468 // types (or that no conversion exists).
1470 return initializer::initialize(storage_, operand);
1473 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
1474 template <typename T>
1475 result_type internal_visit(const T& operand, int) const
1477 return initializer::initialize(storage_, operand);
1481 template <typename T>
1482 int internal_visit(boost::detail::reference_content<T>& operand, long) const
1484 return internal_visit( operand.get(), 1L );
1487 template <typename T>
1488 int internal_visit(const boost::detail::reference_content<T>& operand, long) const
1490 return internal_visit( operand.get(), 1L );
1493 template <typename T>
1494 int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
1496 return internal_visit( operand.get(), 1L );
1499 template <typename T>
1500 int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
1502 return internal_visit( operand.get(), 1L );
1505 template <typename T>
1506 int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1508 return internal_visit( operand.get(), 1L );
1511 template <typename T>
1512 int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
1514 return internal_visit( operand.get(), 1L );
1519 friend class convert_copy_into;
1521 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1522 class convert_move_into
1523 : public static_visitor<int>
1525 private: // representation
1529 public: // structors
1531 explicit convert_move_into(void* storage) BOOST_NOEXCEPT
1536 public: // internal visitor interfaces (below)
1538 template <typename T>
1539 int internal_visit(T& operand, int) const
1542 // Compile error here indicates one of the source variant's types
1543 // cannot be unambiguously converted to the destination variant's
1544 // types (or that no conversion exists).
1546 return initializer::initialize(storage_, detail::variant::move(operand) );
1549 template <typename T>
1550 int internal_visit(boost::detail::reference_content<T>& operand, long) const
1552 return internal_visit( operand.get(), 1L );
1555 template <typename T>
1556 int internal_visit(const boost::detail::reference_content<T>& operand, long) const
1558 return internal_visit( operand.get(), 1L );
1561 template <typename T>
1562 int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
1564 return internal_visit( operand.get(), 1L );
1567 template <typename T>
1568 int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
1570 return internal_visit( operand.get(), 1L );
1573 template <typename T>
1574 int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1576 return internal_visit( operand.get(), 1L );
1579 template <typename T>
1580 int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
1582 return internal_visit( operand.get(), 1L );
1586 friend class convert_move_into;
1589 private: // helpers, for structors, below
1591 template <typename T>
1592 void convert_construct(
1595 , mpl::false_ = mpl::false_() // is_foreign_variant
1599 // Compile error here indicates that the given type is not
1600 // unambiguously convertible to one of the variant's types
1601 // (or that no conversion exists).
1604 initializer::initialize(
1611 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1612 template <typename T>
1613 typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type convert_construct(
1616 , mpl::false_ = mpl::false_() // is_foreign_variant
1620 // Compile error here indicates that the given type is not
1621 // unambiguously convertible to one of the variant's types
1622 // (or that no conversion exists).
1625 initializer::initialize(
1627 , detail::variant::move(operand)
1633 template <typename Variant>
1634 void convert_construct(
1637 , mpl::true_// is_foreign_variant
1640 convert_copy_into visitor(storage_.address());
1642 operand.internal_apply_visitor(visitor)
1646 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1647 template <typename Variant>
1648 typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct(
1651 , mpl::true_// is_foreign_variant
1654 convert_move_into visitor(storage_.address());
1656 operand.internal_apply_visitor(visitor)
1661 template <typename Variant>
1662 void convert_construct_variant(Variant& operand)
1664 // [Determine if the given variant is itself a bounded type, or if its
1665 // content needs to be converted (i.e., it is a 'foreign' variant):]
1668 typedef typename mpl::find_if<
1676 typedef typename mpl::end<types>::type not_found;
1677 typedef typename is_same<
1679 >::type is_foreign_variant;
1681 // Convert construct from operand:
1684 , is_foreign_variant()
1688 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1689 template <typename Variant>
1690 typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct_variant(Variant&& operand)
1692 // [Determine if the given variant is itself a bounded type, or if its
1693 // content needs to be converted (i.e., it is a 'foreign' variant):]
1696 typedef typename mpl::find_if<
1704 typedef typename mpl::end<types>::type not_found;
1705 typedef typename is_same<
1707 >::type is_foreign_variant;
1709 // Convert move construct from operand:
1711 detail::variant::move(operand), 1L
1712 , is_foreign_variant()
1717 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1718 typename boost::enable_if<mpl::or_<
1719 boost::is_same<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>, variant>,
1720 boost::detail::variant::is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&, internal_types>
1721 > >::type convert_construct(
1722 boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1726 convert_construct_variant(operand);
1729 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1730 typename boost::enable_if<mpl::or_<
1731 boost::is_same<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>, variant>,
1732 boost::detail::variant::is_variant_constructible_from<const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&, internal_types>
1733 > >::type convert_construct(
1734 const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1738 convert_construct_variant(operand);
1741 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1742 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1743 typename boost::enable_if<mpl::or_<
1744 boost::is_same<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>, variant>,
1745 boost::detail::variant::is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&&, internal_types>
1746 > >::type convert_construct(
1747 boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&& operand
1751 convert_construct_variant( detail::variant::move(operand) );
1755 public: // structors, cont.
1757 template <typename T>
1758 variant(const T& operand,
1759 typename boost::enable_if<mpl::and_<
1760 mpl::not_< boost::is_same<T, variant> >,
1761 boost::detail::variant::is_variant_constructible_from<const T&, internal_types>
1764 convert_construct(operand, 1L);
1767 template <typename T>
1770 , typename boost::enable_if<mpl::and_<
1771 mpl::not_< is_const<T> >,
1772 mpl::not_< boost::is_same<T, variant> >,
1773 boost::detail::variant::is_variant_constructible_from<T&, internal_types>
1777 convert_construct(operand, 1L);
1780 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1782 variant(T&& operand,
1783 typename boost::enable_if<mpl::and_<
1784 boost::is_rvalue_reference<T&&>,
1785 mpl::not_< boost::is_const<T> >,
1786 mpl::not_< boost::is_same<T, variant> >,
1787 boost::detail::variant::is_variant_constructible_from<T&&, internal_types>
1790 convert_construct( detail::variant::move(operand), 1L);
1794 public: // structors, cont.
1796 // [MSVC6 requires copy constructor appear after template constructors]
1797 variant(const variant& operand)
1799 // Copy the value of operand into *this...
1800 detail::variant::copy_into visitor( storage_.address() );
1801 operand.internal_apply_visitor(visitor);
1803 // ...and activate the *this's primary storage on success:
1804 indicate_which(operand.which());
1807 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1808 variant(variant&& operand) BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value)
1810 // Move the value of operand into *this...
1811 detail::variant::move_into visitor( storage_.address() );
1812 operand.internal_apply_visitor(visitor);
1814 // ...and activate the *this's primary storage on success:
1815 indicate_which(operand.which());
1819 private: // helpers, for modifiers (below)
1821 # if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1822 template <typename Variant>
1823 friend class detail::variant::backup_assigner;
1828 // Internal visitor that "assigns" the visited value to the given variant
1829 // by appropriate destruction and copy-construction.
1833 : public static_visitor<>
1835 protected: // representation
1838 const int rhs_which_;
1840 public: // structors
1842 assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
1844 , rhs_which_(rhs_which)
1848 protected: // helpers, for internal visitor interface (below)
1850 template <typename RhsT, typename B1, typename B2>
1852 const RhsT& rhs_content
1853 , mpl::true_ // has_nothrow_copy
1854 , B1 // is_nothrow_move_constructible
1855 , B2 // has_fallback_type
1856 ) const BOOST_NOEXCEPT
1858 // Destroy lhs's content...
1859 lhs_.destroy_content(); // nothrow
1861 // ...copy rhs content into lhs's storage...
1862 new(lhs_.storage_.address())
1863 RhsT( rhs_content ); // nothrow
1865 // ...and indicate new content type:
1866 lhs_.indicate_which(rhs_which_); // nothrow
1869 template <typename RhsT, typename B>
1871 const RhsT& rhs_content
1872 , mpl::false_ // has_nothrow_copy
1873 , mpl::true_ // is_nothrow_move_constructible
1874 , B // has_fallback_type
1877 // Attempt to make a temporary copy (so as to move it below)...
1878 RhsT temp(rhs_content);
1880 // ...and upon success destroy lhs's content...
1881 lhs_.destroy_content(); // nothrow
1883 // ...move the temporary copy into lhs's storage...
1884 new(lhs_.storage_.address())
1885 RhsT( detail::variant::move(temp) ); // nothrow
1887 // ...and indicate new content type:
1888 lhs_.indicate_which(rhs_which_); // nothrow
1891 void construct_fallback() const BOOST_NOEXCEPT {
1892 // In case of failure, default-construct fallback type in lhs's storage...
1893 new (lhs_.storage_.address())
1894 fallback_type_; // nothrow
1896 // ...indicate construction of fallback type...
1897 lhs_.indicate_which(
1898 BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value
1902 template <typename RhsT>
1904 const RhsT& rhs_content
1905 , mpl::false_ // has_nothrow_copy
1906 , mpl::false_ // is_nothrow_move_constructible
1907 , mpl::true_ // has_fallback_type
1910 // Destroy lhs's content...
1911 lhs_.destroy_content(); // nothrow
1915 // ...and attempt to copy rhs's content into lhs's storage:
1916 new(lhs_.storage_.address())
1917 RhsT( rhs_content );
1921 construct_fallback();
1928 // In the event of success, indicate new content type:
1929 lhs_.indicate_which(rhs_which_); // nothrow
1932 template <typename RhsT>
1934 const RhsT& rhs_content
1935 , mpl::false_ // has_nothrow_copy
1936 , mpl::false_ // is_nothrow_move_constructible
1937 , mpl::false_ // has_fallback_type
1940 detail::variant::backup_assigner<wknd_self_t>
1941 visitor(lhs_, rhs_which_, rhs_content);
1942 lhs_.internal_apply_visitor(visitor);
1945 public: // internal visitor interfaces
1947 template <typename RhsT>
1948 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
1949 internal_visit(const RhsT& rhs_content, int) const
1951 typedef typename has_nothrow_copy<RhsT>::type
1953 typedef typename mpl::or_< // reduces compile-time
1955 , is_nothrow_move_constructible<RhsT>
1956 >::type nothrow_move_constructor;
1961 , nothrow_move_constructor()
1962 , has_fallback_type_()
1965 BOOST_VARIANT_AUX_RETURN_VOID;
1968 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
1970 // silence MSVC warning C4512: assignment operator could not be generated
1971 assigner& operator= (assigner const&);
1975 friend class assigner;
1977 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1978 // class move_assigner
1980 // Internal visitor that "move assigns" the visited value to the given variant
1981 // by appropriate destruction and move-construction.
1987 public: // structors
1989 move_assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
1990 : assigner(lhs, rhs_which)
1994 private: // helpers, for internal visitor interface (below)
1996 template <typename RhsT, typename B2>
1999 , mpl::true_ // has_nothrow_copy
2000 , mpl::false_ // is_nothrow_move_constructible
2001 , B2 // has_fallback_type
2002 ) const BOOST_NOEXCEPT
2004 assigner::assign_impl(rhs_content, mpl::true_(), mpl::false_(), B2());
2007 template <typename RhsT, typename B, typename B2>
2010 , B // has_nothrow_copy
2011 , mpl::true_ // is_nothrow_move_constructible
2012 , B2 // has_fallback_type
2013 ) const BOOST_NOEXCEPT
2015 // ...destroy lhs's content...
2016 assigner::lhs_.destroy_content(); // nothrow
2018 // ...move the rhs_content into lhs's storage...
2019 new(assigner::lhs_.storage_.address())
2020 RhsT( detail::variant::move(rhs_content) ); // nothrow
2022 // ...and indicate new content type:
2023 assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
2026 template <typename RhsT>
2029 , mpl::false_ // has_nothrow_copy
2030 , mpl::false_ // is_nothrow_move_constructible
2031 , mpl::true_ // has_fallback_type
2034 // Destroy lhs's content...
2035 assigner::lhs_.destroy_content(); // nothrow
2039 // ...and attempt to copy rhs's content into lhs's storage:
2040 new(assigner::lhs_.storage_.address())
2041 RhsT( detail::variant::move(rhs_content) );
2045 assigner::construct_fallback();
2052 // In the event of success, indicate new content type:
2053 assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
2056 template <typename RhsT>
2059 , mpl::false_ // has_nothrow_copy
2060 , mpl::false_ // is_nothrow_move_constructible
2061 , mpl::false_ // has_fallback_type
2064 assigner::assign_impl(rhs_content, mpl::false_(), mpl::false_(), mpl::false_());
2067 public: // internal visitor interfaces
2069 template <typename RhsT>
2070 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
2071 internal_visit(RhsT& rhs_content, int) const
2073 typedef typename is_nothrow_move_constructible<RhsT>::type
2074 nothrow_move_constructor;
2075 typedef typename mpl::or_< // reduces compile-time
2076 nothrow_move_constructor
2077 , has_nothrow_copy<RhsT>
2078 >::type nothrow_copy;
2083 , nothrow_move_constructor()
2084 , has_fallback_type_()
2087 BOOST_VARIANT_AUX_RETURN_VOID;
2090 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
2092 // silence MSVC warning C4512: assignment operator could not be generated
2093 move_assigner& operator= (move_assigner const&);
2097 friend class move_assigner;
2098 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2100 void variant_assign(const variant& rhs)
2102 // If the contained types are EXACTLY the same...
2103 if (which_ == rhs.which_)
2105 // ...then assign rhs's storage to lhs's content:
2106 detail::variant::assign_storage visitor(rhs.storage_.address());
2107 this->internal_apply_visitor(visitor);
2111 // Otherwise, perform general (copy-based) variant assignment:
2112 assigner visitor(*this, rhs.which());
2113 rhs.internal_apply_visitor(visitor);
2117 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2118 void variant_assign(variant&& rhs)
2120 // If the contained types are EXACTLY the same...
2121 if (which_ == rhs.which_)
2123 // ...then move rhs's storage to lhs's content:
2124 detail::variant::move_storage visitor(rhs.storage_.address());
2125 this->internal_apply_visitor(visitor);
2129 // Otherwise, perform general (move-based) variant assignment:
2130 move_assigner visitor(*this, rhs.which());
2131 rhs.internal_apply_visitor(visitor);
2134 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2136 private: // helpers, for modifiers (below)
2138 template <typename T>
2139 void assign(const T& rhs)
2141 // If direct T-to-T assignment is not possible...
2142 detail::variant::direct_assigner<T> direct_assign(rhs);
2143 if (this->apply_visitor(direct_assign) == false)
2145 // ...then convert rhs to variant and assign:
2147 // While potentially inefficient, the following construction of a
2148 // variant allows T as any type convertible to one of the bounded
2149 // types without excessive code redundancy.
2152 variant_assign( detail::variant::move(temp) );
2156 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2157 template <typename T>
2158 void move_assign(T&& rhs)
2160 // If direct T-to-T move assignment is not possible...
2161 detail::variant::direct_mover<T> direct_move(rhs);
2162 if (this->apply_visitor(direct_move) == false)
2164 // ...then convert rhs to variant and assign:
2166 // While potentially inefficient, the following construction of a
2167 // variant allows T as any type convertible to one of the bounded
2168 // types without excessive code redundancy.
2170 variant temp( detail::variant::move(rhs) );
2171 variant_assign( detail::variant::move(temp) );
2174 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2176 public: // modifiers
2178 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2180 typename boost::enable_if<
2182 boost::is_rvalue_reference<T&&>,
2183 mpl::not_< boost::is_const<T> >,
2184 boost::detail::variant::is_variant_constructible_from<T&&, internal_types>
2187 >::type operator=(T&& rhs)
2189 move_assign( detail::variant::move(rhs) );
2192 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2194 template <typename T>
2195 typename boost::enable_if<
2197 boost::is_same<T, variant>,
2198 boost::detail::variant::is_variant_constructible_from<const T&, internal_types>
2201 >::type operator=(const T& rhs)
2207 // [MSVC6 requires copy assign appear after templated operator=]
2208 variant& operator=(const variant& rhs)
2210 variant_assign(rhs);
2214 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2215 variant& operator=(variant&& rhs)
2216 #if !defined(__GNUC__) || (__GNUC__ != 4) || (__GNUC_MINOR__ > 6) || defined(__clang__)
2217 BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value && variant_move_noexcept_assignable::type::value)
2220 variant_assign( detail::variant::move(rhs) );
2223 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2225 void swap(variant& rhs)
2227 // If the contained types are the same...
2228 if (which() == rhs.which())
2230 // ...then swap the values directly:
2231 detail::variant::swap_with<variant> visitor(rhs);
2232 this->apply_visitor(visitor);
2236 // ...otherwise, perform general variant swap:
2237 variant tmp( detail::variant::move(rhs) );
2238 rhs = detail::variant::move(*this);
2239 *this = detail::variant::move(tmp);
2246 // NOTE: member which() defined above.
2249 bool empty() const BOOST_NOEXCEPT
2254 const boost::typeindex::type_info& type() const
2256 detail::variant::reflect visitor;
2257 return this->apply_visitor(visitor);
2260 public: // prevent comparison with foreign types
2262 template <typename U>
2263 void operator==(const U&) const
2265 BOOST_STATIC_ASSERT( false && sizeof(U) );
2268 template <typename U>
2269 void operator<(const U&) const
2271 BOOST_STATIC_ASSERT( false && sizeof(U) );
2274 template <typename U>
2275 void operator!=(const U&) const
2277 BOOST_STATIC_ASSERT( false && sizeof(U) );
2280 template <typename U>
2281 void operator>(const U&) const
2283 BOOST_STATIC_ASSERT( false && sizeof(U) );
2286 template <typename U>
2287 void operator<=(const U&) const
2289 BOOST_STATIC_ASSERT( false && sizeof(U) );
2292 template <typename U>
2293 void operator>=(const U&) const
2295 BOOST_STATIC_ASSERT( false && sizeof(U) );
2298 public: // comparison operators
2300 // [MSVC6 requires these operators appear after template operators]
2302 bool operator==(const variant& rhs) const
2304 if (this->which() != rhs.which())
2307 detail::variant::comparer<
2308 variant, detail::variant::equal_comp
2310 return rhs.apply_visitor(visitor);
2313 bool operator<(const variant& rhs) const
2316 // Dirk Schreib suggested this collating order.
2319 if (this->which() != rhs.which())
2320 return this->which() < rhs.which();
2322 detail::variant::comparer<
2323 variant, detail::variant::less_comp
2325 return rhs.apply_visitor(visitor);
2328 ///////////////////////////////////////////////////////////////////////////////
2329 // comparison operators != > <= >=
2330 inline bool operator!=(const variant& rhs) const
2332 return !(*this == rhs);
2335 inline bool operator>(const variant& rhs) const
2340 inline bool operator<=(const variant& rhs) const
2342 return !(*this > rhs);
2345 inline bool operator>=(const variant& rhs) const
2347 return !(*this < rhs);
2350 // helpers, for visitation support (below) -- private when possible
2351 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2353 template < BOOST_VARIANT_ENUM_PARAMS(typename U) >
2354 friend class variant;
2358 #else// defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2362 #endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2364 template <typename Visitor, typename VoidPtrCV>
2366 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2367 typename Visitor::result_type
2369 internal_apply_visitor_impl(
2376 typedef mpl::int_<0> first_which;
2377 typedef typename mpl::begin<internal_types>::type first_it;
2378 typedef typename mpl::end<internal_types>::type last_it;
2380 typedef detail::variant::visitation_impl_step<
2384 return detail::variant::visitation_impl(
2385 internal_which, logical_which
2386 , visitor, storage, mpl::false_()
2387 , never_uses_backup_flag()
2388 , static_cast<first_which*>(0), static_cast<first_step*>(0)
2392 template <typename Visitor>
2393 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2394 typename Visitor::result_type
2396 internal_apply_visitor(Visitor& visitor)
2398 return internal_apply_visitor_impl(
2399 which_, which(), visitor, storage_.address()
2403 template <typename Visitor>
2404 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2405 typename Visitor::result_type
2407 internal_apply_visitor(Visitor& visitor) const
2409 return internal_apply_visitor_impl(
2410 which_, which(), visitor, storage_.address()
2414 public: // visitation support
2416 template <typename Visitor>
2417 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2418 typename Visitor::result_type
2420 apply_visitor(Visitor& visitor)
2422 detail::variant::invoke_visitor<Visitor> invoker(visitor);
2423 return this->internal_apply_visitor(invoker);
2426 template <typename Visitor>
2427 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2428 typename Visitor::result_type
2430 apply_visitor(Visitor& visitor) const
2432 detail::variant::invoke_visitor<Visitor> invoker(visitor);
2433 return this->internal_apply_visitor(invoker);
2438 ///////////////////////////////////////////////////////////////////////////////
2439 // metafunction make_variant_over
2441 // See docs and boost/variant/variant_fwd.hpp for more information.
2443 template <typename Types>
2444 struct make_variant_over
2446 private: // precondition assertions
2448 BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value ));
2450 public: // metafunction result
2453 detail::variant::over_sequence< Types >
2459 ///////////////////////////////////////////////////////////////////////////////
2460 // function template swap
2462 // Swaps two variants of the same type (i.e., identical specification).
2464 template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
2466 variant< BOOST_VARIANT_ENUM_PARAMS(T) >& lhs
2467 , variant< BOOST_VARIANT_ENUM_PARAMS(T) >& rhs
2473 } // namespace boost
2475 // implementation additions
2477 #if !defined(BOOST_NO_IOSTREAM)
2478 #include <boost/variant/detail/variant_io.hpp>
2479 #endif // BOOST_NO_IOSTREAM
2481 #endif // BOOST_VARIANT_VARIANT_HPP