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-2020 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>
35 #include <boost/variant/detail/std_hash.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/integer/common_factor_ct.hpp>
44 #include <boost/static_assert.hpp>
45 #include <boost/preprocessor/cat.hpp>
46 #include <boost/preprocessor/repeat.hpp>
47 #include <boost/type_traits/alignment_of.hpp>
48 #include <boost/type_traits/add_const.hpp>
49 #include <boost/type_traits/has_nothrow_constructor.hpp>
50 #include <boost/type_traits/has_nothrow_copy.hpp>
51 #include <boost/type_traits/is_nothrow_move_assignable.hpp>
52 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
53 #include <boost/type_traits/is_const.hpp>
54 #include <boost/type_traits/is_same.hpp>
55 #include <boost/type_traits/is_rvalue_reference.hpp>
56 #include <boost/type_traits/is_constructible.hpp>
57 #include <boost/type_traits/add_lvalue_reference.hpp>
58 #include <boost/utility/enable_if.hpp>
59 #include <boost/utility/declval.hpp>
60 #include <boost/variant/recursive_wrapper_fwd.hpp>
61 #include <boost/variant/static_visitor.hpp>
63 #include <boost/mpl/assert.hpp>
64 #include <boost/mpl/begin_end.hpp>
65 #include <boost/mpl/bool.hpp>
66 #include <boost/mpl/deref.hpp>
67 #include <boost/mpl/empty.hpp>
68 #include <boost/mpl/eval_if.hpp>
69 #include <boost/mpl/find_if.hpp>
70 #include <boost/mpl/fold.hpp>
71 #include <boost/mpl/front.hpp>
72 #include <boost/mpl/identity.hpp>
73 #include <boost/mpl/if.hpp>
74 #include <boost/mpl/insert_range.hpp>
75 #include <boost/mpl/int.hpp>
76 #include <boost/mpl/is_sequence.hpp>
77 #include <boost/mpl/iterator_range.hpp>
78 #include <boost/mpl/iter_fold_if.hpp>
79 #include <boost/mpl/list.hpp>
80 #include <boost/mpl/logical.hpp>
81 #include <boost/mpl/max_element.hpp>
82 #include <boost/mpl/next.hpp>
83 #include <boost/mpl/not.hpp>
84 #include <boost/mpl/pair.hpp>
85 #include <boost/mpl/protect.hpp>
86 #include <boost/mpl/push_front.hpp>
87 #include <boost/mpl/same_as.hpp>
88 #include <boost/mpl/size_t.hpp>
89 #include <boost/mpl/sizeof.hpp>
90 #include <boost/mpl/transform.hpp>
92 ///////////////////////////////////////////////////////////////////////////////
93 // Implementation Macros:
95 // BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
96 // Defined in boost/variant/detail/visitation_impl.hpp.
98 // BOOST_VARIANT_MINIMIZE_SIZE
99 // When #defined, implementation employs all known means to minimize the
100 // size of variant obje cts. However, often unsuccessful due to alignment
101 // issues, and potentially harmful to runtime speed, so not enabled by
102 // default. (TODO: Investigate further.)
104 #if defined(BOOST_VARIANT_MINIMIZE_SIZE)
105 # include <climits> // for SCHAR_MAX
106 # include <boost/mpl/eval_if.hpp>
107 # include <boost/mpl/equal_to.hpp>
108 # include <boost/mpl/identity.hpp>
109 # include <boost/mpl/int.hpp>
110 # include <boost/mpl/if.hpp>
111 # include <boost/mpl/less.hpp>
112 # include <boost/mpl/long.hpp>
113 # include <boost/mpl/O1_size.hpp>
119 namespace detail { namespace variant {
121 ///////////////////////////////////////////////////////////////////////////////
122 // (detail) metafunction max_value
124 // Finds the maximum value of the unary metafunction F over Sequence.
126 template <typename Sequence, typename F>
129 private: // helpers, for metafunction result (below)
131 typedef typename mpl::transform1<Sequence, F>::type transformed_;
132 typedef typename mpl::max_element<transformed_
136 public: // metafunction result
138 typedef typename mpl::deref<max_it>::type
145 template <typename State, typename Item>
148 ::boost::integer::static_lcm<
149 BOOST_MPL_AUX_VALUE_WKND(State)::value
150 , ::boost::alignment_of<Item>::value
156 ///////////////////////////////////////////////////////////////////////////////
157 // (detail) metafunction find_fallback_type
159 // Provides a fallback (i.e., nothrow default-constructible) type from the
160 // specified sequence, or no_fallback_type if not found.
162 // This implementation is designed to prefer boost::blank over other potential
163 // fallback types, regardless of its position in the specified sequence.
166 class no_fallback_type;
168 struct find_fallback_type_pred
170 template <typename Iterator>
174 typedef typename mpl::deref<Iterator>::type t_;
177 typedef mpl::not_< has_nothrow_constructor<t_> > type;
181 template <typename Types>
182 struct find_fallback_type
184 private: // helpers, for metafunction result (below)
186 typedef typename mpl::end<Types>::type end_it;
188 // [Find the first suitable fallback type...]
190 typedef typename mpl::iter_fold_if<
192 , mpl::int_<0>, mpl::protect< mpl::next<> >
193 , mpl::protect< find_fallback_type_pred >
194 >::type first_result_;
196 typedef typename first_result_::first first_result_index;
197 typedef typename first_result_::second first_result_it;
199 // [...now search the rest of the sequence for boost::blank...]
201 typedef typename mpl::iter_fold_if<
202 mpl::iterator_range< first_result_it,end_it >
203 , first_result_index, mpl::protect< mpl::next<> >
204 , mpl::protect< mpl::not_same_as<boost::blank> >
205 >::type second_result_;
207 typedef typename second_result_::second second_result_it;
209 public: // metafunction result
211 // [...and return the results of the search:]
212 typedef typename mpl::eval_if<
213 is_same< second_result_it,end_it >
215 is_same< first_result_it,end_it >
216 , mpl::pair< no_fallback_type,no_fallback_type >
219 , mpl::identity< second_result_ >
224 #ifndef BOOST_NO_CXX11_NOEXCEPT
225 ///////////////////////////////////////////////////////////////////////////////
226 // (detail) metafunction is_variant_move_noexcept_constructible
228 // Returns true_type if all the types are nothrow move constructible.
230 template <class Types>
231 struct is_variant_move_noexcept_constructible {
232 typedef typename boost::mpl::find_if<
233 Types, mpl::not_<boost::is_nothrow_move_constructible<boost::mpl::_1> >
236 typedef typename boost::mpl::end<Types>::type end_t;
237 typedef typename boost::is_same<
242 ///////////////////////////////////////////////////////////////////////////////
243 // (detail) metafunction is_variant_move_noexcept_assignable
245 // Returns true_type if all the types are nothrow move constructible.
247 template <class Types>
248 struct is_variant_move_noexcept_assignable {
249 typedef typename boost::mpl::find_if<
250 Types, mpl::not_<boost::is_nothrow_move_assignable<boost::mpl::_1> >
253 typedef typename boost::mpl::end<Types>::type end_t;
254 typedef typename boost::is_same<
258 #endif // BOOST_NO_CXX11_NOEXCEPT
260 ///////////////////////////////////////////////////////////////////////////////
261 // (detail) metafunction is_variant_constructible_from
263 // Derives from true_type if at least one variant's type is constructible from T.
265 template <class T1, class T2>
266 struct is_constructible_ext:
268 boost::is_constructible<
272 boost::is_constructible<
274 typename boost::add_lvalue_reference<T2>::type
279 template <class T, class Types>
280 struct is_variant_constructible_from:
281 boost::mpl::not_< boost::is_same<
282 typename boost::mpl::find_if<
284 is_constructible_ext<boost::mpl::_1, T>
286 typename boost::mpl::end<Types>::type
290 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
291 struct is_variant_constructible_from< boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >:
293 typename boost::mpl::find_if<
294 typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::recursive_enabled_types,
295 mpl::not_< is_variant_constructible_from< boost::mpl::_1, Types> >
297 typename boost::mpl::end< typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::recursive_enabled_types >::type
301 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
302 struct is_variant_constructible_from< const boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& , Types >:
303 is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >
306 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
307 struct is_variant_constructible_from< boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& , Types >:
308 is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >
311 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
313 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
314 struct is_variant_constructible_from< boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>&& , Types >:
315 is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >
318 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
319 struct is_variant_constructible_from< boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const && , Types >:
320 is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >
323 #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCE
326 ///////////////////////////////////////////////////////////////////////////////
327 // (detail) metafunction make_storage
329 // Provides an aligned storage type capable of holding any of the types
330 // specified in the given type-sequence.
333 template <typename Types, typename NeverUsesBackupFlag>
336 private: // helpers, for metafunction result (below)
338 typedef typename mpl::eval_if<
340 , mpl::identity< Types >
342 Types, backup_holder<void*>
346 typedef typename max_value<
347 types, mpl::sizeof_<mpl::_1>
350 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
352 typedef typename mpl::fold<
356 >::type max_alignment;
360 // temporary workaround -- use maximal alignment
361 typedef mpl::size_t< -1 > max_alignment;
363 #endif // borland workaround
365 public: // metafunction result
367 typedef ::boost::aligned_storage<
368 BOOST_MPL_AUX_VALUE_WKND(max_size)::value
369 , BOOST_MPL_AUX_VALUE_WKND(max_alignment)::value
373 ///////////////////////////////////////////////////////////////////////////////
374 // (detail) class destroyer
376 // Internal visitor that destroys the value it visits.
379 : public static_visitor<>
381 public: // visitor interfaces
383 template <typename T>
384 void internal_visit(T& operand, int) const BOOST_NOEXCEPT
386 operand.~T(); // must be noexcept
388 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551)) || \
389 BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
390 (void)operand; // suppresses warnings
396 ///////////////////////////////////////////////////////////////////////////////
397 // (detail) class template known_get
399 // Visitor that returns a reference to content of the specified type.
401 // Precondition: visited variant MUST contain logical content of type T.
403 template <typename T>
405 : public static_visitor<T&>
408 public: // visitor interface
410 T& operator()(T& operand) const BOOST_NOEXCEPT
415 template <typename U>
416 T& operator()(U&) const
418 // logical error to be here: see precondition above
419 return ::boost::detail::variant::forced_return< T& >();
423 ///////////////////////////////////////////////////////////////////////////////
424 // (detail) class copy_into
426 // Internal visitor that copies the value it visits into the given buffer.
429 : public static_visitor<>
431 private: // representation
437 explicit copy_into(void* storage) BOOST_NOEXCEPT
442 public: // internal visitor interface
444 template <typename T>
445 void internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
447 new(storage_) T( operand.get() );
450 template <typename T>
451 void internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
453 new(storage_) T( operand.get() );
456 template <typename T>
457 void internal_visit(const T& operand, int) const
459 new(storage_) T(operand);
464 ///////////////////////////////////////////////////////////////////////////////
465 // (detail) class move_into
467 // Internal visitor that moves the value it visits into the given buffer.
469 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
471 : public static_visitor<>
473 private: // representation
479 explicit move_into(void* storage) BOOST_NOEXCEPT
484 public: // internal visitor interface
486 template <typename T>
487 void internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
489 new(storage_) T( ::boost::detail::variant::move(operand.get()) );
492 template <typename T>
493 void internal_visit(T& operand, int) const BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(boost::declval<T>())))
495 new(storage_) T(::boost::detail::variant::move(operand));
500 ///////////////////////////////////////////////////////////////////////////////
501 // (detail) class assign_storage
503 // Internal visitor that assigns the given storage (which must be a
504 // constructed value of the same type) to the value it visits.
506 struct assign_storage
507 : public static_visitor<>
509 private: // representation
511 const void* rhs_storage_;
515 explicit assign_storage(const void* rhs_storage) BOOST_NOEXCEPT
516 : rhs_storage_(rhs_storage)
520 public: // internal visitor interfaces
522 template <typename T>
523 void internal_visit(backup_holder<T>& lhs_content, long) const
526 = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
529 template <typename T>
530 void internal_visit(const backup_holder<T>& lhs_content, long) const
533 = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
536 template <typename T>
537 void internal_visit(T& lhs_content, int) const
540 // Compile error here indicates one of variant's bounded types does
541 // not meet the requirements of the Assignable concept. Thus,
542 // variant is not Assignable.
544 // Hint: Are any of the bounded types const-qualified or references?
546 lhs_content = *static_cast< const T* >(rhs_storage_);
551 ///////////////////////////////////////////////////////////////////////////////
552 // (detail) class move_storage
554 // Internal visitor that moves the given storage (which must be a
555 // constructed value of the same type) to the value it visits.
558 : public static_visitor<>
560 private: // representation
566 explicit move_storage(void* rhs_storage) BOOST_NOEXCEPT
567 : rhs_storage_(rhs_storage)
571 public: // internal visitor interfaces
573 template <typename T>
574 void internal_visit(backup_holder<T>& lhs_content, long) const
577 = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
580 template <typename T>
581 void internal_visit(const backup_holder<T>& lhs_content, long) const
584 = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
587 template <typename T>
588 void internal_visit(T& lhs_content, int) const
591 // Compile error here indicates one of variant's bounded types does
592 // not meet the requirements of the Assignable concept. Thus,
593 // variant is not Assignable.
595 // Hint: Are any of the bounded types const-qualified or references?
597 lhs_content = ::boost::detail::variant::move(*static_cast<T* >(rhs_storage_));
602 ///////////////////////////////////////////////////////////////////////////////
603 // (detail) class direct_assigner
605 // Generic static visitor that: if and only if the visited value is of the
606 // specified type, assigns the given value to the visited value and returns
607 // true; else returns false.
609 template <typename T>
610 class direct_assigner
611 : public static_visitor<bool>
613 private: // representation
619 explicit direct_assigner(const T& rhs) BOOST_NOEXCEPT
624 public: // visitor interface
626 bool operator()(T& lhs)
632 template <typename U>
633 bool operator()(U&) BOOST_NOEXCEPT
638 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
640 // silence MSVC warning C4512: assignment operator could not be generated
641 direct_assigner& operator= (direct_assigner const&);
645 ///////////////////////////////////////////////////////////////////////////////
646 // (detail) class direct_mover
648 // Generic static visitor that: if and only if the visited value is of the
649 // specified type, move assigns the given value to the visited value and returns
650 // true; else returns false.
652 template <typename T>
654 : public static_visitor<bool>
656 private: // representation
662 explicit direct_mover(T& rhs) BOOST_NOEXCEPT
667 public: // visitor interface
669 bool operator()(T& lhs)
671 lhs = ::boost::detail::variant::move(rhs_);
675 template <typename U>
676 bool operator()(U&) BOOST_NOEXCEPT
681 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
683 // silence MSVC warning C4512: assignment operator could not be generated
684 direct_mover& operator= (direct_mover const&);
689 ///////////////////////////////////////////////////////////////////////////////
690 // (detail) class backup_assigner
692 // Internal visitor that "assigns" the given value to the visited value,
693 // using backup to recover if the destroy-copy sequence fails.
695 // NOTE: This needs to be a friend of variant, as it needs access to
696 // indicate_which, indicate_backup_which, etc.
698 template <typename Variant>
699 class backup_assigner
700 : public static_visitor<>
702 private: // representation
706 const void* rhs_content_;
707 void (*copy_rhs_content_)(void*, const void*);
712 backup_assigner(Variant& lhs, int rhs_which, const RhsT& rhs_content)
714 , rhs_which_(rhs_which)
715 , rhs_content_(&rhs_content)
716 , copy_rhs_content_(&construct_impl<RhsT>)
720 private: // helpers, for visitor interface (below)
723 static void construct_impl(void* addr, const void* obj)
725 new(addr) RhsT(*static_cast<const RhsT*>(obj));
728 template <typename LhsT>
729 void backup_assign_impl(
730 backup_holder<LhsT>& lhs_content
731 , mpl::false_ // is_nothrow_move_constructible
735 // Move lhs content to backup...
736 backup_holder<LhsT> backup_lhs_content(0);
737 backup_lhs_content.swap(lhs_content); // nothrow
739 // ...destroy lhs content...
740 lhs_content.~backup_holder<LhsT>(); // nothrow
744 // ...and attempt to copy rhs content into lhs storage:
745 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
749 // In case of failure, copy backup pointer to lhs storage...
750 new(lhs_.storage_.address())
751 backup_holder<LhsT>( 0 ); // nothrow
753 static_cast<backup_holder<LhsT>* >(lhs_.storage_.address())
754 ->swap(backup_lhs_content); // nothrow
761 // In case of success, indicate new content type:
762 lhs_.indicate_which(rhs_which_); // nothrow
765 template <typename LhsT>
766 void backup_assign_impl(
768 , mpl::true_ // is_nothrow_move_constructible
772 // Move lhs content to backup...
773 LhsT backup_lhs_content(
774 ::boost::detail::variant::move(lhs_content)
777 // ...destroy lhs content...
778 lhs_content.~LhsT(); // nothrow
782 // ...and attempt to copy rhs content into lhs storage:
783 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
787 // In case of failure, restore backup content to lhs storage...
788 new(lhs_.storage_.address())
790 ::boost::detail::variant::move(backup_lhs_content)
798 // In case of success, indicate new content type:
799 lhs_.indicate_which(rhs_which_); // nothrow
802 template <typename LhsT>
803 void backup_assign_impl(
805 , mpl::false_ // is_nothrow_move_constructible
809 // Backup lhs content...
810 LhsT* backup_lhs_ptr = new LhsT(lhs_content);
812 // ...destroy lhs content...
813 lhs_content.~LhsT(); // nothrow
817 // ...and attempt to copy rhs content into lhs storage:
818 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
822 // In case of failure, copy backup pointer to lhs storage...
823 new(lhs_.storage_.address())
824 backup_holder<LhsT>( backup_lhs_ptr ); // nothrow
826 // ...indicate now using backup...
827 lhs_.indicate_backup_which( lhs_.which() ); // nothrow
834 // In case of success, indicate new content type...
835 lhs_.indicate_which(rhs_which_); // nothrow
837 // ...and delete backup:
838 delete backup_lhs_ptr; // nothrow
841 public: // visitor interface
843 template <typename LhsT>
844 void internal_visit(LhsT& lhs_content, int)
846 typedef typename is_nothrow_move_constructible<LhsT>::type
849 backup_assign_impl( lhs_content, nothrow_move(), 1L);
852 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
854 // silence MSVC warning C4512: assignment operator could not be generated
855 backup_assigner& operator= (backup_assigner const&);
859 ///////////////////////////////////////////////////////////////////////////////
860 // (detail) class swap_with
862 // Visitor that swaps visited value with content of given variant.
864 // Precondition: Given variant MUST have same logical type as visited value.
866 template <typename Variant>
868 : public static_visitor<>
870 private: // representation
876 explicit swap_with(Variant& toswap) BOOST_NOEXCEPT
881 public: // internal visitor interfaces
883 template <typename T>
884 void operator()(T& operand) const
886 // Since the precondition ensures types are same, get T...
888 T& other = toswap_.apply_visitor(getter);
891 ::boost::detail::variant::move_swap( operand, other );
895 swap_with& operator=(const swap_with&);
899 ///////////////////////////////////////////////////////////////////////////////
900 // (detail) class reflect
902 // Generic static visitor that performs a typeid on the value it visits.
906 : public static_visitor<const boost::typeindex::type_info&>
908 public: // visitor interfaces
910 template <typename T>
911 const boost::typeindex::type_info& operator()(const T&) const BOOST_NOEXCEPT
913 return boost::typeindex::type_id<T>().type_info();
918 ///////////////////////////////////////////////////////////////////////////////
919 // (detail) class comparer
921 // Generic static visitor that compares the content of the given lhs variant
922 // with the visited rhs content using Comp.
924 // Precondition: lhs.which() == rhs.which()
926 template <typename Variant, typename Comp>
928 : public static_visitor<bool>
930 private: // representation
936 explicit comparer(const Variant& lhs) BOOST_NOEXCEPT
941 public: // visitor interfaces
943 template <typename T>
944 bool operator()(T& rhs_content) const
946 // Since the precondition ensures lhs and rhs types are same, get T...
948 const T& lhs_content = lhs_.apply_visitor(getter);
950 // ...and compare lhs and rhs contents:
951 return Comp()(lhs_content, rhs_content);
955 comparer& operator=(const comparer&);
959 ///////////////////////////////////////////////////////////////////////////////
960 // (detail) class equal_comp
962 // Generic function object compares lhs with rhs using operator==.
966 template <typename T>
967 bool operator()(const T& lhs, const T& rhs) const
973 ///////////////////////////////////////////////////////////////////////////////
974 // (detail) class less_comp
976 // Generic function object compares lhs with rhs using operator<.
980 template <typename T>
981 bool operator()(const T& lhs, const T& rhs) const
987 ///////////////////////////////////////////////////////////////////////////////
988 // (detail) class template invoke_visitor
990 // Internal visitor that invokes the given visitor using:
991 // * for wrappers (e.g., recursive_wrapper), the wrapper's held value.
992 // * for all other values, the value itself.
994 template <typename Visitor, bool MoveSemantics>
997 private: // representation
1001 public: // visitor typedefs
1003 typedef typename Visitor::result_type
1006 public: // structors
1008 explicit invoke_visitor(Visitor& visitor) BOOST_NOEXCEPT
1013 public: // internal visitor interfaces
1015 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1017 //using workaround with is_same<T, T> to prenvent compilation error, because we need to use T in enable_if to make SFINAE work
1018 template <typename T>
1019 typename enable_if_c<MoveSemantics && is_same<T, T>::value, result_type>::type internal_visit(T&& operand, int)
1021 return visitor_(::boost::move<T>(operand));
1024 //using workaround with is_same<T, T> to prenvent compilation error, because we need to use T in enable_if to make SFINAE work
1025 template <typename T>
1026 typename disable_if_c<MoveSemantics && is_same<T, T>::value, result_type>::type internal_visit(T&& operand, int)
1028 return visitor_(operand);
1033 template <typename T>
1034 result_type internal_visit(T& operand, int)
1036 return visitor_(operand);
1039 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
1040 template <typename T>
1041 result_type internal_visit(const T& operand, int)
1043 return visitor_(operand);
1047 #endif //RVALUE REFERENCES
1049 public: // internal visitor interfaces, cont.
1051 template <typename T>
1052 result_type internal_visit(boost::recursive_wrapper<T>& operand, long)
1054 return internal_visit( operand.get(), 1L );
1057 template <typename T>
1058 result_type internal_visit(const boost::recursive_wrapper<T>& operand, long)
1060 return internal_visit( operand.get(), 1L );
1063 template <typename T>
1064 result_type internal_visit(boost::detail::reference_content<T>& operand, long)
1066 return internal_visit( operand.get(), 1L );
1069 template <typename T>
1070 result_type internal_visit(const boost::detail::reference_content<T>& operand, long)
1072 return internal_visit( operand.get(), 1L );
1075 template <typename T>
1076 result_type internal_visit(boost::detail::variant::backup_holder<T>& operand, long)
1078 return internal_visit( operand.get(), 1L );
1081 template <typename T>
1082 result_type internal_visit(const boost::detail::variant::backup_holder<T>& operand, long)
1084 return internal_visit( operand.get(), 1L );
1087 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
1089 // silence MSVC warning C4512: assignment operator could not be generated
1090 invoke_visitor& operator= (invoke_visitor const&);
1094 }} // namespace detail::variant
1096 ///////////////////////////////////////////////////////////////////////////////
1097 // class template variant (concept inspired by Andrei Alexandrescu)
1099 // See docs and boost/variant/variant_fwd.hpp for more information.
1103 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)
1107 private: // helpers, for typedefs (below)
1109 typedef variant wknd_self_t;
1111 struct is_recursive_
1112 : detail::variant::is_recursive_flag<T0_>
1116 typedef typename mpl::eval_if<
1119 , mpl::identity< T0_ >
1120 >::type unwrapped_T0_;
1122 struct is_sequence_based_
1123 : detail::variant::is_over_sequence<unwrapped_T0_>
1127 #if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
1129 private: // helpers, for typedefs (below)
1131 typedef typename mpl::eval_if<
1133 , unwrapped_T0_ // over_sequence<...>::type
1134 , detail::variant::make_variant_list<
1136 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
1138 >::type specified_types;
1140 BOOST_STATIC_ASSERT((
1141 ::boost::mpl::not_< mpl::empty<specified_types> >::value
1144 public: // public typedefs
1145 typedef typename mpl::eval_if<
1150 detail::variant::quoted_enable_recursive<wknd_self_t>
1153 , mpl::identity< specified_types >
1154 >::type recursive_enabled_types; // used by is_variant_constructible_from<> trait
1156 typedef typename mpl::transform<
1157 recursive_enabled_types
1158 , unwrap_recursive<mpl::_1>
1161 private: // internal typedefs
1163 typedef typename mpl::transform<
1164 recursive_enabled_types
1165 , mpl::protect< detail::make_reference_content<> >
1166 >::type internal_types;
1168 typedef typename mpl::front<
1170 >::type internal_T0;
1172 #else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
1174 private: // helpers, for typedefs (below)
1176 typedef unwrapped_T0_ T0;
1178 #define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
1179 typedef typename mpl::eval_if< \
1181 , detail::variant::enable_recursive< \
1185 , mpl::identity< BOOST_PP_CAT(T,N) > \
1186 >::type BOOST_PP_CAT(recursive_enabled_T,N); \
1190 BOOST_VARIANT_LIMIT_TYPES
1191 , BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1195 #undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1197 #define BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS(z,N,_) \
1198 typedef typename unwrap_recursive< \
1199 BOOST_PP_CAT(recursive_enabled_T,N) \
1200 >::type BOOST_PP_CAT(public_T,N); \
1204 BOOST_VARIANT_LIMIT_TYPES
1205 , BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1209 #undef BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1211 public: // public typedefs
1213 typedef typename detail::variant::make_variant_list<
1214 BOOST_VARIANT_ENUM_PARAMS(public_T)
1217 private: // helpers, for internal typedefs (below)
1219 #define BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS(z,N,_) \
1220 typedef detail::make_reference_content< \
1221 BOOST_PP_CAT(recursive_enabled_T,N) \
1222 >::type BOOST_PP_CAT(internal_T,N); \
1226 BOOST_VARIANT_LIMIT_TYPES
1227 , BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1231 #undef BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1233 private: // internal typedefs
1235 typedef typename detail::variant::make_variant_list<
1236 BOOST_VARIANT_ENUM_PARAMS(internal_T)
1237 >::type internal_types;
1239 private: // static precondition assertions
1242 // variant< type-sequence > syntax is not supported on this compiler!
1244 BOOST_MPL_ASSERT_NOT(( is_sequence_based_ ));
1246 #endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT workaround
1248 private: // helpers, for representation (below)
1250 typedef typename detail::variant::find_fallback_type<
1252 >::type fallback_type_result_;
1254 typedef typename fallback_type_result_::first
1255 fallback_type_index_;
1256 typedef typename fallback_type_result_::second
1259 struct has_fallback_type_
1261 is_same< fallback_type_, detail::variant::no_fallback_type >
1266 typedef has_fallback_type_
1267 never_uses_backup_flag;
1269 typedef typename detail::variant::make_storage<
1270 internal_types, never_uses_backup_flag
1273 #ifndef BOOST_NO_CXX11_NOEXCEPT
1274 typedef typename detail::variant::is_variant_move_noexcept_constructible<
1276 > variant_move_noexcept_constructible;
1278 typedef typename detail::variant::is_variant_move_noexcept_assignable<
1280 > variant_move_noexcept_assignable;
1284 private: // helpers, for representation (below)
1287 // * [0, size<internal_types>) indicates stack content
1288 // * [-size<internal_types>, 0) indicates pointer to heap backup
1290 // * then which() -> which_
1291 // * else which() -> -(which_ + 1)
1293 #if !defined(BOOST_VARIANT_MINIMIZE_SIZE)
1295 typedef int which_t;
1297 #else // defined(BOOST_VARIANT_MINIMIZE_SIZE)
1299 // [if O1_size available, then attempt which_t size optimization...]
1300 // [select signed char if fewer than SCHAR_MAX types, else signed int:]
1301 typedef typename mpl::eval_if<
1302 mpl::equal_to< mpl::O1_size<internal_types>, mpl::long_<-1> >
1303 , mpl::identity< int >
1305 mpl::less< mpl::O1_size<internal_types>, mpl::int_<SCHAR_MAX> >
1311 #endif // BOOST_VARIANT_MINIMIZE_SIZE switch
1313 // representation -- private when possible
1314 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1323 void indicate_which(int which_arg) BOOST_NOEXCEPT
1325 which_ = static_cast<which_t>( which_arg );
1328 void indicate_backup_which(int which_arg) BOOST_NOEXCEPT
1330 which_ = static_cast<which_t>( -(which_arg + 1) );
1333 private: // helpers, for queries (below)
1335 bool using_backup() const BOOST_NOEXCEPT
1342 int which() const BOOST_NOEXCEPT
1344 // If using heap backup...
1346 // ...then return adjusted which_:
1347 return -(which_ + 1);
1349 // Otherwise, return which_ directly:
1353 private: // helpers, for structors (below)
1356 : BOOST_VARIANT_AUX_INITIALIZER_T(
1357 recursive_enabled_types, recursive_enabled_T
1362 void destroy_content() BOOST_NOEXCEPT
1364 detail::variant::destroyer visitor;
1365 this->internal_apply_visitor(visitor);
1368 public: // structors
1370 ~variant() BOOST_NOEXCEPT
1376 #if !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130))
1377 BOOST_NOEXCEPT_IF(boost::has_nothrow_constructor<internal_T0>::value)
1381 #pragma warning( push )
1382 // behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized
1383 #pragma warning( disable : 4345 )
1386 // Compile error from here indicates that the first bound
1387 // type is not default-constructible, and so variant cannot
1388 // support its own default-construction.
1390 new( storage_.address() ) internal_T0();
1391 indicate_which(0); // zero is the index of the first bounded type
1393 #pragma warning( pop )
1397 private: // helpers, for structors, cont. (below)
1399 class convert_copy_into
1400 : public static_visitor<int>
1402 private: // representation
1406 public: // structors
1408 explicit convert_copy_into(void* storage) BOOST_NOEXCEPT
1413 public: // internal visitor interfaces (below)
1415 template <typename T>
1416 int internal_visit(T& operand, int) const
1419 // Compile error here indicates one of the source variant's types
1420 // cannot be unambiguously converted to the destination variant's
1421 // types (or that no conversion exists).
1423 return initializer::initialize(storage_, operand);
1426 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
1427 template <typename T>
1428 result_type internal_visit(const T& operand, int) const
1430 return initializer::initialize(storage_, operand);
1434 template <typename T>
1435 int internal_visit(boost::detail::reference_content<T>& operand, long) const
1437 return internal_visit( operand.get(), 1L );
1440 template <typename T>
1441 int internal_visit(const boost::detail::reference_content<T>& operand, long) const
1443 return internal_visit( operand.get(), 1L );
1446 template <typename T>
1447 int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
1449 return internal_visit( operand.get(), 1L );
1452 template <typename T>
1453 int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
1455 return internal_visit( operand.get(), 1L );
1458 template <typename T>
1459 int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1461 return internal_visit( operand.get(), 1L );
1464 template <typename T>
1465 int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
1467 return internal_visit( operand.get(), 1L );
1472 friend class convert_copy_into;
1474 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1475 class convert_move_into
1476 : public static_visitor<int>
1478 private: // representation
1482 public: // structors
1484 explicit convert_move_into(void* storage) BOOST_NOEXCEPT
1489 public: // internal visitor interfaces (below)
1491 template <typename T>
1492 int internal_visit(T& operand, int) const
1495 // Compile error here indicates one of the source variant's types
1496 // cannot be unambiguously converted to the destination variant's
1497 // types (or that no conversion exists).
1499 return initializer::initialize(storage_, detail::variant::move(operand) );
1502 template <typename T>
1503 int internal_visit(boost::detail::reference_content<T>& operand, long) const
1505 return internal_visit( operand.get(), 1L );
1508 template <typename T>
1509 int internal_visit(const boost::detail::reference_content<T>& operand, long) const
1511 return internal_visit( operand.get(), 1L );
1514 template <typename T>
1515 int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
1517 return internal_visit( operand.get(), 1L );
1520 template <typename T>
1521 int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
1523 return internal_visit( operand.get(), 1L );
1526 template <typename T>
1527 int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1529 return internal_visit( operand.get(), 1L );
1532 template <typename T>
1533 int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
1535 return internal_visit( operand.get(), 1L );
1539 friend class convert_move_into;
1542 private: // helpers, for structors, below
1544 template <typename T>
1545 void convert_construct(
1548 , mpl::false_ = mpl::false_() // is_foreign_variant
1552 // Compile error here indicates that the given type is not
1553 // unambiguously convertible to one of the variant's types
1554 // (or that no conversion exists).
1557 initializer::initialize(
1564 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1565 template <typename T>
1566 typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type convert_construct(
1569 , mpl::false_ = mpl::false_() // is_foreign_variant
1573 // Compile error here indicates that the given type is not
1574 // unambiguously convertible to one of the variant's types
1575 // (or that no conversion exists).
1578 initializer::initialize(
1580 , detail::variant::move(operand)
1586 template <typename Variant>
1587 void convert_construct(
1590 , mpl::true_// is_foreign_variant
1593 convert_copy_into visitor(storage_.address());
1595 operand.internal_apply_visitor(visitor)
1599 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1600 template <typename Variant>
1601 typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct(
1604 , mpl::true_// is_foreign_variant
1607 convert_move_into visitor(storage_.address());
1609 operand.internal_apply_visitor(visitor)
1614 template <typename Variant>
1615 void convert_construct_variant(Variant& operand)
1617 // [Determine if the given variant is itself a bounded type, or if its
1618 // content needs to be converted (i.e., it is a 'foreign' variant):]
1621 typedef typename mpl::find_if<
1629 typedef typename mpl::end<types>::type not_found;
1630 typedef typename is_same<
1632 >::type is_foreign_variant;
1634 // Convert construct from operand:
1637 , is_foreign_variant()
1641 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1642 template <typename Variant>
1643 typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct_variant(Variant&& operand)
1645 // [Determine if the given variant is itself a bounded type, or if its
1646 // content needs to be converted (i.e., it is a 'foreign' variant):]
1649 typedef typename mpl::find_if<
1657 typedef typename mpl::end<types>::type not_found;
1658 typedef typename is_same<
1660 >::type is_foreign_variant;
1662 // Convert move construct from operand:
1664 detail::variant::move(operand), 1L
1665 , is_foreign_variant()
1670 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1671 typename boost::enable_if<mpl::or_<
1672 boost::is_same<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>, variant>,
1673 boost::detail::variant::is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&, internal_types>
1674 > >::type convert_construct(
1675 boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1679 convert_construct_variant(operand);
1682 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1683 typename boost::enable_if<mpl::or_<
1684 boost::is_same<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>, variant>,
1685 boost::detail::variant::is_variant_constructible_from<const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&, internal_types>
1686 > >::type convert_construct(
1687 const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1691 convert_construct_variant(operand);
1694 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1695 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1696 typename boost::enable_if<mpl::or_<
1697 boost::is_same<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>, variant>,
1698 boost::detail::variant::is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&&, internal_types>
1699 > >::type convert_construct(
1700 boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&& operand
1704 convert_construct_variant( detail::variant::move(operand) );
1708 public: // structors, cont.
1710 template <typename T>
1711 variant(const T& operand,
1712 typename boost::enable_if<mpl::or_<
1714 mpl::not_< boost::is_same<T, variant> >,
1715 boost::detail::variant::is_variant_constructible_from<const T&, internal_types>
1717 boost::is_same<T, boost::recursive_variant_> >,
1718 bool >::type = true)
1720 convert_construct(operand, 1L);
1723 template <typename T>
1726 , typename boost::enable_if<mpl::or_<
1728 mpl::not_< is_const<T> >,
1729 mpl::not_< boost::is_same<T, variant> >,
1730 boost::detail::variant::is_variant_constructible_from<T&, internal_types>
1732 boost::is_same<T, boost::recursive_variant_> >,
1736 convert_construct(operand, 1L);
1739 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1741 variant(T&& operand,
1742 typename boost::enable_if<mpl::or_<
1744 boost::is_rvalue_reference<T&&>,
1745 mpl::not_< boost::is_const<T> >,
1746 mpl::not_< boost::is_same<T, variant> >,
1747 boost::detail::variant::is_variant_constructible_from<T&&, internal_types>
1749 boost::is_same<T, boost::recursive_variant_> >,
1750 bool >::type = true)
1752 convert_construct( detail::variant::move(operand), 1L);
1756 public: // structors, cont.
1758 // [MSVC6 requires copy constructor appear after template constructors]
1759 variant(const variant& operand)
1761 // Copy the value of operand into *this...
1762 detail::variant::copy_into visitor( storage_.address() );
1763 operand.internal_apply_visitor(visitor);
1765 // ...and activate the *this's primary storage on success:
1766 indicate_which(operand.which());
1769 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1770 variant(variant&& operand) BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value)
1772 // Move the value of operand into *this...
1773 detail::variant::move_into visitor( storage_.address() );
1774 operand.internal_apply_visitor(visitor);
1776 // ...and activate the *this's primary storage on success:
1777 indicate_which(operand.which());
1781 private: // helpers, for modifiers (below)
1783 # if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1784 template <typename Variant>
1785 friend class detail::variant::backup_assigner;
1790 // Internal visitor that "assigns" the visited value to the given variant
1791 // by appropriate destruction and copy-construction.
1795 : public static_visitor<>
1797 protected: // representation
1800 const int rhs_which_;
1802 public: // structors
1804 assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
1806 , rhs_which_(rhs_which)
1810 protected: // helpers, for internal visitor interface (below)
1812 template <typename RhsT, typename B1, typename B2>
1814 const RhsT& rhs_content
1815 , mpl::true_ // has_nothrow_copy
1816 , B1 // is_nothrow_move_constructible
1817 , B2 // has_fallback_type
1818 ) const BOOST_NOEXCEPT
1820 // Destroy lhs's content...
1821 lhs_.destroy_content(); // nothrow
1823 // ...copy rhs content into lhs's storage...
1824 new(lhs_.storage_.address())
1825 RhsT( rhs_content ); // nothrow
1827 // ...and indicate new content type:
1828 lhs_.indicate_which(rhs_which_); // nothrow
1831 template <typename RhsT, typename B>
1833 const RhsT& rhs_content
1834 , mpl::false_ // has_nothrow_copy
1835 , mpl::true_ // is_nothrow_move_constructible
1836 , B // has_fallback_type
1839 // Attempt to make a temporary copy (so as to move it below)...
1840 RhsT temp(rhs_content);
1842 // ...and upon success destroy lhs's content...
1843 lhs_.destroy_content(); // nothrow
1845 // ...move the temporary copy into lhs's storage...
1846 new(lhs_.storage_.address())
1847 RhsT( detail::variant::move(temp) ); // nothrow
1849 // ...and indicate new content type:
1850 lhs_.indicate_which(rhs_which_); // nothrow
1853 void construct_fallback() const BOOST_NOEXCEPT {
1854 // In case of failure, default-construct fallback type in lhs's storage...
1855 new (lhs_.storage_.address())
1856 fallback_type_; // nothrow
1858 // ...indicate construction of fallback type...
1859 lhs_.indicate_which(
1860 BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value
1864 template <typename RhsT>
1866 const RhsT& rhs_content
1867 , mpl::false_ // has_nothrow_copy
1868 , mpl::false_ // is_nothrow_move_constructible
1869 , mpl::true_ // has_fallback_type
1872 // Destroy lhs's content...
1873 lhs_.destroy_content(); // nothrow
1877 // ...and attempt to copy rhs's content into lhs's storage:
1878 new(lhs_.storage_.address())
1879 RhsT( rhs_content );
1883 construct_fallback();
1890 // In the event of success, indicate new content type:
1891 lhs_.indicate_which(rhs_which_); // nothrow
1894 template <typename RhsT>
1896 const RhsT& rhs_content
1897 , mpl::false_ // has_nothrow_copy
1898 , mpl::false_ // is_nothrow_move_constructible
1899 , mpl::false_ // has_fallback_type
1902 detail::variant::backup_assigner<wknd_self_t>
1903 visitor(lhs_, rhs_which_, rhs_content);
1904 lhs_.internal_apply_visitor(visitor);
1907 public: // internal visitor interfaces
1909 template <typename RhsT>
1910 void internal_visit(const RhsT& rhs_content, int) const
1912 typedef typename has_nothrow_copy<RhsT>::type
1914 typedef typename mpl::or_< // reduces compile-time
1916 , is_nothrow_move_constructible<RhsT>
1917 >::type nothrow_move_constructor;
1922 , nothrow_move_constructor()
1923 , has_fallback_type_()
1927 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
1929 // silence MSVC warning C4512: assignment operator could not be generated
1930 assigner& operator= (assigner const&);
1934 friend class assigner;
1936 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1937 // class move_assigner
1939 // Internal visitor that "move assigns" the visited value to the given variant
1940 // by appropriate destruction and move-construction.
1946 public: // structors
1948 move_assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
1949 : assigner(lhs, rhs_which)
1953 private: // helpers, for internal visitor interface (below)
1955 template <typename RhsT, typename B2>
1958 , mpl::true_ // has_nothrow_copy
1959 , mpl::false_ // is_nothrow_move_constructible
1960 , B2 // has_fallback_type
1961 ) const BOOST_NOEXCEPT
1963 assigner::assign_impl(rhs_content, mpl::true_(), mpl::false_(), B2());
1966 template <typename RhsT, typename B, typename B2>
1969 , B // has_nothrow_copy
1970 , mpl::true_ // is_nothrow_move_constructible
1971 , B2 // has_fallback_type
1972 ) const BOOST_NOEXCEPT
1974 // ...destroy lhs's content...
1975 assigner::lhs_.destroy_content(); // nothrow
1977 // ...move the rhs_content into lhs's storage...
1978 new(assigner::lhs_.storage_.address())
1979 RhsT( detail::variant::move(rhs_content) ); // nothrow
1981 // ...and indicate new content type:
1982 assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
1985 template <typename RhsT>
1988 , mpl::false_ // has_nothrow_copy
1989 , mpl::false_ // is_nothrow_move_constructible
1990 , mpl::true_ // has_fallback_type
1993 // Destroy lhs's content...
1994 assigner::lhs_.destroy_content(); // nothrow
1998 // ...and attempt to copy rhs's content into lhs's storage:
1999 new(assigner::lhs_.storage_.address())
2000 RhsT( detail::variant::move(rhs_content) );
2004 assigner::construct_fallback();
2011 // In the event of success, indicate new content type:
2012 assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
2015 template <typename RhsT>
2018 , mpl::false_ // has_nothrow_copy
2019 , mpl::false_ // is_nothrow_move_constructible
2020 , mpl::false_ // has_fallback_type
2023 assigner::assign_impl(rhs_content, mpl::false_(), mpl::false_(), mpl::false_());
2026 public: // internal visitor interfaces
2028 template <typename RhsT>
2029 void internal_visit(RhsT& rhs_content, int) const
2031 typedef typename is_nothrow_move_constructible<RhsT>::type
2032 nothrow_move_constructor;
2033 typedef typename mpl::or_< // reduces compile-time
2034 nothrow_move_constructor
2035 , has_nothrow_copy<RhsT>
2036 >::type nothrow_copy;
2041 , nothrow_move_constructor()
2042 , has_fallback_type_()
2046 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
2048 // silence MSVC warning C4512: assignment operator could not be generated
2049 move_assigner& operator= (move_assigner const&);
2053 friend class move_assigner;
2054 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2056 void variant_assign(const variant& rhs)
2058 // If the contained types are EXACTLY the same...
2059 if (which_ == rhs.which_)
2061 // ...then assign rhs's storage to lhs's content:
2062 detail::variant::assign_storage visitor(rhs.storage_.address());
2063 this->internal_apply_visitor(visitor);
2067 // Otherwise, perform general (copy-based) variant assignment:
2068 assigner visitor(*this, rhs.which());
2069 rhs.internal_apply_visitor(visitor);
2073 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2074 void variant_assign(variant&& rhs)
2076 // If the contained types are EXACTLY the same...
2077 if (which_ == rhs.which_)
2079 // ...then move rhs's storage to lhs's content:
2080 detail::variant::move_storage visitor(rhs.storage_.address());
2081 this->internal_apply_visitor(visitor);
2085 // Otherwise, perform general (move-based) variant assignment:
2086 move_assigner visitor(*this, rhs.which());
2087 rhs.internal_apply_visitor(visitor);
2090 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2092 private: // helpers, for modifiers (below)
2094 template <typename T>
2095 void assign(const T& rhs)
2097 // If direct T-to-T assignment is not possible...
2098 detail::variant::direct_assigner<T> direct_assign(rhs);
2099 if (this->apply_visitor(direct_assign) == false)
2101 // ...then convert rhs to variant and assign:
2103 // While potentially inefficient, the following construction of a
2104 // variant allows T as any type convertible to one of the bounded
2105 // types without excessive code redundancy.
2108 variant_assign( detail::variant::move(temp) );
2112 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2113 template <typename T>
2114 void move_assign(T&& rhs)
2116 // If direct T-to-T move assignment is not possible...
2117 detail::variant::direct_mover<T> direct_move(rhs);
2118 if (this->apply_visitor(direct_move) == false)
2120 // ...then convert rhs to variant and assign:
2122 // While potentially inefficient, the following construction of a
2123 // variant allows T as any type convertible to one of the bounded
2124 // types without excessive code redundancy.
2126 variant temp( detail::variant::move(rhs) );
2127 variant_assign( detail::variant::move(temp) );
2130 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2132 public: // modifiers
2134 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2136 typename boost::enable_if<
2138 boost::is_rvalue_reference<T&&>,
2139 mpl::not_< boost::is_const<T> >,
2140 boost::detail::variant::is_variant_constructible_from<T&&, internal_types>
2143 >::type operator=(T&& rhs)
2145 move_assign( detail::variant::move(rhs) );
2148 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2150 template <typename T>
2151 typename boost::enable_if<
2153 boost::is_same<T, variant>,
2154 boost::detail::variant::is_variant_constructible_from<const T&, internal_types>
2157 >::type operator=(const T& rhs)
2163 // [MSVC6 requires copy assign appear after templated operator=]
2164 variant& operator=(const variant& rhs)
2166 variant_assign(rhs);
2170 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2171 variant& operator=(variant&& rhs)
2172 #if !defined(__GNUC__) || (__GNUC__ != 4) || (__GNUC_MINOR__ > 6) || defined(__clang__)
2173 BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value && variant_move_noexcept_assignable::type::value)
2176 variant_assign( detail::variant::move(rhs) );
2179 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2181 void swap(variant& rhs)
2183 // If the contained types are the same...
2184 if (which() == rhs.which())
2186 // ...then swap the values directly:
2187 detail::variant::swap_with<variant> visitor(rhs);
2188 this->apply_visitor(visitor);
2192 // ...otherwise, perform general variant swap:
2193 variant tmp( detail::variant::move(rhs) );
2194 rhs = detail::variant::move(*this);
2195 *this = detail::variant::move(tmp);
2202 // NOTE: member which() defined above.
2205 bool empty() const BOOST_NOEXCEPT
2210 const boost::typeindex::type_info& type() const
2212 detail::variant::reflect visitor;
2213 return this->apply_visitor(visitor);
2216 public: // prevent comparison with foreign types
2218 template <typename U>
2219 void operator==(const U&) const
2221 BOOST_STATIC_ASSERT( false && sizeof(U) );
2224 template <typename U>
2225 void operator<(const U&) const
2227 BOOST_STATIC_ASSERT( false && sizeof(U) );
2230 template <typename U>
2231 void operator!=(const U&) const
2233 BOOST_STATIC_ASSERT( false && sizeof(U) );
2236 template <typename U>
2237 void operator>(const U&) const
2239 BOOST_STATIC_ASSERT( false && sizeof(U) );
2242 template <typename U>
2243 void operator<=(const U&) const
2245 BOOST_STATIC_ASSERT( false && sizeof(U) );
2248 template <typename U>
2249 void operator>=(const U&) const
2251 BOOST_STATIC_ASSERT( false && sizeof(U) );
2254 public: // comparison operators
2256 // [MSVC6 requires these operators appear after template operators]
2258 bool operator==(const variant& rhs) const
2260 if (this->which() != rhs.which())
2263 detail::variant::comparer<
2264 variant, detail::variant::equal_comp
2266 return rhs.apply_visitor(visitor);
2269 bool operator<(const variant& rhs) const
2272 // Dirk Schreib suggested this collating order.
2275 if (this->which() != rhs.which())
2276 return this->which() < rhs.which();
2278 detail::variant::comparer<
2279 variant, detail::variant::less_comp
2281 return rhs.apply_visitor(visitor);
2284 ///////////////////////////////////////////////////////////////////////////////
2285 // comparison operators != > <= >=
2286 inline bool operator!=(const variant& rhs) const
2288 return !(*this == rhs);
2291 inline bool operator>(const variant& rhs) const
2296 inline bool operator<=(const variant& rhs) const
2298 return !(*this > rhs);
2301 inline bool operator>=(const variant& rhs) const
2303 return !(*this < rhs);
2306 // helpers, for visitation support (below) -- private when possible
2307 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2309 template < BOOST_VARIANT_ENUM_PARAMS(typename U) >
2310 friend class variant;
2314 #else// defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2318 #endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2320 template <typename Visitor, typename VoidPtrCV>
2321 BOOST_FORCEINLINE static typename Visitor::result_type
2322 internal_apply_visitor_impl(
2329 typedef mpl::int_<0> first_which;
2330 typedef typename mpl::begin<internal_types>::type first_it;
2331 typedef typename mpl::end<internal_types>::type last_it;
2333 typedef detail::variant::visitation_impl_step<
2337 return detail::variant::visitation_impl(
2338 internal_which, logical_which
2339 , visitor, storage, mpl::false_()
2340 , never_uses_backup_flag()
2341 , static_cast<first_which*>(0), static_cast<first_step*>(0)
2345 template <typename Visitor>
2346 BOOST_FORCEINLINE typename Visitor::result_type
2347 internal_apply_visitor(Visitor& visitor)
2349 return internal_apply_visitor_impl(
2350 which_, which(), visitor, storage_.address()
2354 template <typename Visitor>
2355 BOOST_FORCEINLINE typename Visitor::result_type
2356 internal_apply_visitor(Visitor& visitor) const
2358 return internal_apply_visitor_impl(
2359 which_, which(), visitor, storage_.address()
2363 public: // visitation support
2365 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
2367 template <typename Visitor>
2368 typename Visitor::result_type
2369 apply_visitor(Visitor& visitor) &&
2371 detail::variant::invoke_visitor<Visitor, true> invoker(visitor);
2372 return this->internal_apply_visitor(invoker);
2375 template <typename Visitor>
2376 typename Visitor::result_type
2377 apply_visitor(Visitor& visitor) const&&
2379 detail::variant::invoke_visitor<Visitor, true> invoker(visitor);
2380 return this->internal_apply_visitor(invoker);
2385 template <typename Visitor>
2386 typename Visitor::result_type
2387 apply_visitor(Visitor& visitor)
2388 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
2392 detail::variant::invoke_visitor<Visitor, false> invoker(visitor);
2393 return this->internal_apply_visitor(invoker);
2396 template <typename Visitor>
2397 typename Visitor::result_type
2398 apply_visitor(Visitor& visitor) const
2399 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
2403 detail::variant::invoke_visitor<Visitor, false> invoker(visitor);
2404 return this->internal_apply_visitor(invoker);
2409 ///////////////////////////////////////////////////////////////////////////////
2410 // metafunction make_variant_over
2412 // See docs and boost/variant/variant_fwd.hpp for more information.
2414 template <typename Types>
2415 struct make_variant_over
2417 private: // precondition assertions
2419 BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value ));
2420 typedef typename boost::mpl::insert_range<
2422 , boost::mpl::end< boost::mpl::list<> >::type
2424 >::type copied_sequence_t;
2426 public: // metafunction result
2429 detail::variant::over_sequence<copied_sequence_t>
2434 ///////////////////////////////////////////////////////////////////////////////
2435 // function template swap
2437 // Swaps two variants of the same type (i.e., identical specification).
2439 template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
2441 variant< BOOST_VARIANT_ENUM_PARAMS(T) >& lhs
2442 , variant< BOOST_VARIANT_ENUM_PARAMS(T) >& rhs
2448 } // namespace boost
2450 // implementation additions
2452 #if !defined(BOOST_NO_IOSTREAM)
2453 #include <boost/variant/detail/variant_io.hpp>
2454 #endif // BOOST_NO_IOSTREAM
2456 #endif // BOOST_VARIANT_VARIANT_HPP