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/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::math::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 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
385 internal_visit(T& operand, int) const BOOST_NOEXCEPT
387 operand.~T(); // must be noexcept
389 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551)) || \
390 BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
391 (void)operand; // suppresses warnings
394 BOOST_VARIANT_AUX_RETURN_VOID;
399 ///////////////////////////////////////////////////////////////////////////////
400 // (detail) class template known_get
402 // Visitor that returns a reference to content of the specified type.
404 // Precondition: visited variant MUST contain logical content of type T.
406 template <typename T>
408 : public static_visitor<T&>
411 public: // visitor interface
413 T& operator()(T& operand) const BOOST_NOEXCEPT
418 template <typename U>
419 T& operator()(U&) const
421 // logical error to be here: see precondition above
422 return ::boost::detail::variant::forced_return< T& >();
426 ///////////////////////////////////////////////////////////////////////////////
427 // (detail) class copy_into
429 // Internal visitor that copies the value it visits into the given buffer.
432 : public static_visitor<>
434 private: // representation
440 explicit copy_into(void* storage) BOOST_NOEXCEPT
445 public: // internal visitor interface
447 template <typename T>
448 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
449 internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
451 new(storage_) T( operand.get() );
452 BOOST_VARIANT_AUX_RETURN_VOID;
455 template <typename T>
456 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
457 internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
459 new(storage_) T( operand.get() );
460 BOOST_VARIANT_AUX_RETURN_VOID;
463 template <typename T>
464 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
465 internal_visit(const T& operand, int) const
467 new(storage_) T(operand);
468 BOOST_VARIANT_AUX_RETURN_VOID;
473 ///////////////////////////////////////////////////////////////////////////////
474 // (detail) class move_into
476 // Internal visitor that moves the value it visits into the given buffer.
478 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
480 : public static_visitor<>
482 private: // representation
488 explicit move_into(void* storage) BOOST_NOEXCEPT
493 public: // internal visitor interface
495 template <typename T>
496 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
497 internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
499 new(storage_) T( ::boost::detail::variant::move(operand.get()) );
500 BOOST_VARIANT_AUX_RETURN_VOID;
503 template <typename T>
504 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
505 internal_visit(T& operand, int) const BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(boost::declval<T>())))
507 new(storage_) T(::boost::detail::variant::move(operand));
508 BOOST_VARIANT_AUX_RETURN_VOID;
513 ///////////////////////////////////////////////////////////////////////////////
514 // (detail) class assign_storage
516 // Internal visitor that assigns the given storage (which must be a
517 // constructed value of the same type) to the value it visits.
519 struct assign_storage
520 : public static_visitor<>
522 private: // representation
524 const void* rhs_storage_;
528 explicit assign_storage(const void* rhs_storage) BOOST_NOEXCEPT
529 : rhs_storage_(rhs_storage)
533 public: // internal visitor interfaces
535 template <typename T>
536 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
537 internal_visit(backup_holder<T>& lhs_content, long) const
540 = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
541 BOOST_VARIANT_AUX_RETURN_VOID;
544 template <typename T>
545 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
546 internal_visit(const backup_holder<T>& lhs_content, long) const
549 = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
550 BOOST_VARIANT_AUX_RETURN_VOID;
553 template <typename T>
554 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
555 internal_visit(T& lhs_content, int) const
558 // Compile error here indicates one of variant's bounded types does
559 // not meet the requirements of the Assignable concept. Thus,
560 // variant is not Assignable.
562 // Hint: Are any of the bounded types const-qualified or references?
564 lhs_content = *static_cast< const T* >(rhs_storage_);
565 BOOST_VARIANT_AUX_RETURN_VOID;
570 ///////////////////////////////////////////////////////////////////////////////
571 // (detail) class move_storage
573 // Internal visitor that moves the given storage (which must be a
574 // constructed value of the same type) to the value it visits.
577 : public static_visitor<>
579 private: // representation
585 explicit move_storage(void* rhs_storage) BOOST_NOEXCEPT
586 : rhs_storage_(rhs_storage)
590 public: // internal visitor interfaces
592 template <typename T>
593 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
594 internal_visit(backup_holder<T>& lhs_content, long) const
597 = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
598 BOOST_VARIANT_AUX_RETURN_VOID;
601 template <typename T>
602 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
603 internal_visit(const backup_holder<T>& lhs_content, long) const
606 = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
607 BOOST_VARIANT_AUX_RETURN_VOID;
610 template <typename T>
611 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
612 internal_visit(T& lhs_content, int) const
615 // Compile error here indicates one of variant's bounded types does
616 // not meet the requirements of the Assignable concept. Thus,
617 // variant is not Assignable.
619 // Hint: Are any of the bounded types const-qualified or references?
621 lhs_content = ::boost::detail::variant::move(*static_cast<T* >(rhs_storage_));
622 BOOST_VARIANT_AUX_RETURN_VOID;
627 ///////////////////////////////////////////////////////////////////////////////
628 // (detail) class direct_assigner
630 // Generic static visitor that: if and only if the visited value is of the
631 // specified type, assigns the given value to the visited value and returns
632 // true; else returns false.
634 template <typename T>
635 class direct_assigner
636 : public static_visitor<bool>
638 private: // representation
644 explicit direct_assigner(const T& rhs) BOOST_NOEXCEPT
649 public: // visitor interface
651 bool operator()(T& lhs)
657 template <typename U>
658 bool operator()(U&) BOOST_NOEXCEPT
663 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
665 // silence MSVC warning C4512: assignment operator could not be generated
666 direct_assigner& operator= (direct_assigner const&);
670 ///////////////////////////////////////////////////////////////////////////////
671 // (detail) class direct_mover
673 // Generic static visitor that: if and only if the visited value is of the
674 // specified type, move assigns the given value to the visited value and returns
675 // true; else returns false.
677 template <typename T>
679 : public static_visitor<bool>
681 private: // representation
687 explicit direct_mover(T& rhs) BOOST_NOEXCEPT
692 public: // visitor interface
694 bool operator()(T& lhs)
696 lhs = ::boost::detail::variant::move(rhs_);
700 template <typename U>
701 bool operator()(U&) BOOST_NOEXCEPT
706 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
708 // silence MSVC warning C4512: assignment operator could not be generated
709 direct_mover& operator= (direct_mover const&);
714 ///////////////////////////////////////////////////////////////////////////////
715 // (detail) class backup_assigner
717 // Internal visitor that "assigns" the given value to the visited value,
718 // using backup to recover if the destroy-copy sequence fails.
720 // NOTE: This needs to be a friend of variant, as it needs access to
721 // indicate_which, indicate_backup_which, etc.
723 template <typename Variant>
724 class backup_assigner
725 : public static_visitor<>
727 private: // representation
731 const void* rhs_content_;
732 void (*copy_rhs_content_)(void*, const void*);
737 backup_assigner(Variant& lhs, int rhs_which, const RhsT& rhs_content)
739 , rhs_which_(rhs_which)
740 , rhs_content_(&rhs_content)
741 , copy_rhs_content_(&construct_impl<RhsT>)
745 private: // helpers, for visitor interface (below)
748 static void construct_impl(void* addr, const void* obj)
750 new(addr) RhsT(*static_cast<const RhsT*>(obj));
753 template <typename LhsT>
754 void backup_assign_impl(
755 backup_holder<LhsT>& lhs_content
756 , mpl::false_ // is_nothrow_move_constructible
760 // Move lhs content to backup...
761 backup_holder<LhsT> backup_lhs_content(0);
762 backup_lhs_content.swap(lhs_content); // nothrow
764 // ...destroy lhs content...
765 lhs_content.~backup_holder<LhsT>(); // nothrow
769 // ...and attempt to copy rhs content into lhs storage:
770 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
774 // In case of failure, copy backup pointer to lhs storage...
775 new(lhs_.storage_.address())
776 backup_holder<LhsT>( 0 ); // nothrow
778 static_cast<backup_holder<LhsT>* >(lhs_.storage_.address())
779 ->swap(backup_lhs_content); // nothrow
786 // In case of success, indicate new content type:
787 lhs_.indicate_which(rhs_which_); // nothrow
790 template <typename LhsT>
791 void backup_assign_impl(
793 , mpl::true_ // is_nothrow_move_constructible
797 // Move lhs content to backup...
798 LhsT backup_lhs_content(
799 ::boost::detail::variant::move(lhs_content)
802 // ...destroy lhs content...
803 lhs_content.~LhsT(); // nothrow
807 // ...and attempt to copy rhs content into lhs storage:
808 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
812 // In case of failure, restore backup content to lhs storage...
813 new(lhs_.storage_.address())
815 ::boost::detail::variant::move(backup_lhs_content)
823 // In case of success, indicate new content type:
824 lhs_.indicate_which(rhs_which_); // nothrow
827 template <typename LhsT>
828 void backup_assign_impl(
830 , mpl::false_ // is_nothrow_move_constructible
834 // Backup lhs content...
835 LhsT* backup_lhs_ptr = new LhsT(lhs_content);
837 // ...destroy lhs content...
838 lhs_content.~LhsT(); // nothrow
842 // ...and attempt to copy rhs content into lhs storage:
843 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
847 // In case of failure, copy backup pointer to lhs storage...
848 new(lhs_.storage_.address())
849 backup_holder<LhsT>( backup_lhs_ptr ); // nothrow
851 // ...indicate now using backup...
852 lhs_.indicate_backup_which( lhs_.which() ); // nothrow
859 // In case of success, indicate new content type...
860 lhs_.indicate_which(rhs_which_); // nothrow
862 // ...and delete backup:
863 delete backup_lhs_ptr; // nothrow
866 public: // visitor interface
868 template <typename LhsT>
869 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
870 internal_visit(LhsT& lhs_content, int)
872 typedef typename is_nothrow_move_constructible<LhsT>::type
875 backup_assign_impl( lhs_content, nothrow_move(), 1L);
877 BOOST_VARIANT_AUX_RETURN_VOID;
880 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
882 // silence MSVC warning C4512: assignment operator could not be generated
883 backup_assigner& operator= (backup_assigner const&);
887 ///////////////////////////////////////////////////////////////////////////////
888 // (detail) class swap_with
890 // Visitor that swaps visited value with content of given variant.
892 // Precondition: Given variant MUST have same logical type as visited value.
894 template <typename Variant>
896 : public static_visitor<>
898 private: // representation
904 explicit swap_with(Variant& toswap) BOOST_NOEXCEPT
909 public: // internal visitor interfaces
911 template <typename T>
912 void operator()(T& operand) const
914 // Since the precondition ensures types are same, get T...
916 T& other = toswap_.apply_visitor(getter);
919 ::boost::detail::variant::move_swap( operand, other );
923 swap_with& operator=(const swap_with&);
927 ///////////////////////////////////////////////////////////////////////////////
928 // (detail) class reflect
930 // Generic static visitor that performs a typeid on the value it visits.
934 : public static_visitor<const boost::typeindex::type_info&>
936 public: // visitor interfaces
938 template <typename T>
939 const boost::typeindex::type_info& operator()(const T&) const BOOST_NOEXCEPT
941 return boost::typeindex::type_id<T>().type_info();
946 ///////////////////////////////////////////////////////////////////////////////
947 // (detail) class comparer
949 // Generic static visitor that compares the content of the given lhs variant
950 // with the visited rhs content using Comp.
952 // Precondition: lhs.which() == rhs.which()
954 template <typename Variant, typename Comp>
956 : public static_visitor<bool>
958 private: // representation
964 explicit comparer(const Variant& lhs) BOOST_NOEXCEPT
969 public: // visitor interfaces
971 template <typename T>
972 bool operator()(T& rhs_content) const
974 // Since the precondition ensures lhs and rhs types are same, get T...
976 const T& lhs_content = lhs_.apply_visitor(getter);
978 // ...and compare lhs and rhs contents:
979 return Comp()(lhs_content, rhs_content);
983 comparer& operator=(const comparer&);
987 ///////////////////////////////////////////////////////////////////////////////
988 // (detail) class equal_comp
990 // Generic function object compares lhs with rhs using operator==.
994 template <typename T>
995 bool operator()(const T& lhs, const T& rhs) const
1001 ///////////////////////////////////////////////////////////////////////////////
1002 // (detail) class less_comp
1004 // Generic function object compares lhs with rhs using operator<.
1008 template <typename T>
1009 bool operator()(const T& lhs, const T& rhs) const
1015 ///////////////////////////////////////////////////////////////////////////////
1016 // (detail) class template invoke_visitor
1018 // Internal visitor that invokes the given visitor using:
1019 // * for wrappers (e.g., recursive_wrapper), the wrapper's held value.
1020 // * for all other values, the value itself.
1022 template <typename Visitor, bool MoveSemantics>
1023 class invoke_visitor
1025 private: // representation
1029 public: // visitor typedefs
1031 typedef typename Visitor::result_type
1034 public: // structors
1036 explicit invoke_visitor(Visitor& visitor) BOOST_NOEXCEPT
1041 #if !defined(BOOST_NO_VOID_RETURNS)
1043 public: // internal visitor interfaces
1045 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1047 //using workaround with is_same<T, T> to prenvent compilation error, because we need to use T in enable_if to make SFINAE work
1048 template <typename T>
1049 typename enable_if_c<MoveSemantics && is_same<T, T>::value, result_type>::type internal_visit(T&& operand, int)
1051 return visitor_(::boost::move<T>(operand));
1054 //using workaround with is_same<T, T> to prenvent compilation error, because we need to use T in enable_if to make SFINAE work
1055 template <typename T>
1056 typename disable_if_c<MoveSemantics && is_same<T, T>::value, result_type>::type internal_visit(T&& operand, int)
1058 return visitor_(operand);
1063 template <typename T>
1064 result_type internal_visit(T& operand, int)
1066 return visitor_(operand);
1069 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
1070 template <typename T>
1071 result_type internal_visit(const T& operand, int)
1073 return visitor_(operand);
1077 #endif //RVALUE REFERENCES
1079 #else // defined(BOOST_NO_VOID_RETURNS)
1081 private: // helpers, for internal visitor interfaces (below)
1083 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1085 //using workaround with is_same<T, T> to prenvent compilation error, because we need to use T in enable_if to make SFINAE work
1086 template <typename T>
1087 typename enable_if<mpl::and_<MoveSemantics && is_same<T, T>::value>, BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)>::type
1088 visit_impl(T&& operand, mpl::false_)
1090 return visitor_(::boost::move(operand));
1093 //using workaround with is_same<T, T> to prenvent compilation error, because we need to use T in enable_if to make SFINAE work
1094 template <typename T>
1095 typename enable_if_c<MoveSemantics && is_same<T, T>::value, BOOST_VARIANT_AUX_RETURN_VOID_TYPE>::type
1096 visit_impl(T&& operand, mpl::true_)
1098 visitor_(::boost::move(operand));
1099 BOOST_VARIANT_AUX_RETURN_VOID;
1102 //using workaround with is_same<T, T> to prenvent compilation error, because we need to use T in enable_if to make SFINAE work
1103 template <typename T>
1104 typename disable_if_c<MoveSemantics && is_same<T, T>::value, BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)>::type
1105 visit_impl(T&& operand, mpl::false_)
1107 return visitor_(operand);
1110 //using workaround with is_same<T, T> to prenvent compilation error, because we need to use T in enable_if to make SFINAE work
1111 template <typename T>
1112 typename disable_if<MoveSemantics && is_same<T, T>::value, BOOST_VARIANT_AUX_RETURN_VOID_TYPE>::type
1113 visit_impl(T&& operand, mpl::true_)
1116 BOOST_VARIANT_AUX_RETURN_VOID;
1121 template <typename T>
1122 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1123 visit_impl(T& operand, mpl::false_)
1125 return visitor_(operand);
1128 template <typename T>
1129 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
1130 visit_impl(T& operand, mpl::true_)
1133 BOOST_VARIANT_AUX_RETURN_VOID;
1136 #endif //RVALUE_REFERENCES
1138 public: // internal visitor interfaces
1140 template <typename T>
1141 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1142 internal_visit(T& operand, int)
1144 typedef typename is_same<result_type, void>::type
1145 has_void_result_type;
1147 return visit_impl(operand, has_void_result_type());
1150 #endif // BOOST_NO_VOID_RETURNS) workaround
1152 public: // internal visitor interfaces, cont.
1154 template <typename T>
1155 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1156 internal_visit(boost::recursive_wrapper<T>& operand, long)
1158 return internal_visit( operand.get(), 1L );
1161 template <typename T>
1162 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1163 internal_visit(const boost::recursive_wrapper<T>& operand, long)
1165 return internal_visit( operand.get(), 1L );
1168 template <typename T>
1169 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1170 internal_visit(boost::detail::reference_content<T>& operand, long)
1172 return internal_visit( operand.get(), 1L );
1175 template <typename T>
1176 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1177 internal_visit(const boost::detail::reference_content<T>& operand, long)
1179 return internal_visit( operand.get(), 1L );
1182 template <typename T>
1183 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1184 internal_visit(boost::detail::variant::backup_holder<T>& operand, long)
1186 return internal_visit( operand.get(), 1L );
1189 template <typename T>
1190 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
1191 internal_visit(const boost::detail::variant::backup_holder<T>& operand, long)
1193 return internal_visit( operand.get(), 1L );
1196 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
1198 // silence MSVC warning C4512: assignment operator could not be generated
1199 invoke_visitor& operator= (invoke_visitor const&);
1203 }} // namespace detail::variant
1205 ///////////////////////////////////////////////////////////////////////////////
1206 // class template variant (concept inspired by Andrei Alexandrescu)
1208 // See docs and boost/variant/variant_fwd.hpp for more information.
1212 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)
1216 private: // helpers, for typedefs (below)
1218 typedef variant wknd_self_t;
1220 struct is_recursive_
1221 : detail::variant::is_recursive_flag<T0_>
1225 typedef typename mpl::eval_if<
1228 , mpl::identity< T0_ >
1229 >::type unwrapped_T0_;
1231 struct is_sequence_based_
1232 : detail::variant::is_over_sequence<unwrapped_T0_>
1236 #if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
1238 private: // helpers, for typedefs (below)
1240 typedef typename mpl::eval_if<
1242 , unwrapped_T0_ // over_sequence<...>::type
1243 , detail::variant::make_variant_list<
1245 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
1247 >::type specified_types;
1249 BOOST_STATIC_ASSERT((
1250 ::boost::mpl::not_< mpl::empty<specified_types> >::value
1253 public: // public typedefs
1254 typedef typename mpl::eval_if<
1259 detail::variant::quoted_enable_recursive<wknd_self_t>
1262 , mpl::identity< specified_types >
1263 >::type recursive_enabled_types; // used by is_variant_constructible_from<> trait
1265 typedef typename mpl::transform<
1266 recursive_enabled_types
1267 , unwrap_recursive<mpl::_1>
1270 private: // internal typedefs
1272 typedef typename mpl::transform<
1273 recursive_enabled_types
1274 , mpl::protect< detail::make_reference_content<> >
1275 >::type internal_types;
1277 typedef typename mpl::front<
1279 >::type internal_T0;
1281 #else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
1283 private: // helpers, for typedefs (below)
1285 typedef unwrapped_T0_ T0;
1287 #define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
1288 typedef typename mpl::eval_if< \
1290 , detail::variant::enable_recursive< \
1294 , mpl::identity< BOOST_PP_CAT(T,N) > \
1295 >::type BOOST_PP_CAT(recursive_enabled_T,N); \
1299 BOOST_VARIANT_LIMIT_TYPES
1300 , BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1304 #undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1306 #define BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS(z,N,_) \
1307 typedef typename unwrap_recursive< \
1308 BOOST_PP_CAT(recursive_enabled_T,N) \
1309 >::type BOOST_PP_CAT(public_T,N); \
1313 BOOST_VARIANT_LIMIT_TYPES
1314 , BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1318 #undef BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1320 public: // public typedefs
1322 typedef typename detail::variant::make_variant_list<
1323 BOOST_VARIANT_ENUM_PARAMS(public_T)
1326 private: // helpers, for internal typedefs (below)
1328 #define BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS(z,N,_) \
1329 typedef detail::make_reference_content< \
1330 BOOST_PP_CAT(recursive_enabled_T,N) \
1331 >::type BOOST_PP_CAT(internal_T,N); \
1335 BOOST_VARIANT_LIMIT_TYPES
1336 , BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1340 #undef BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1342 private: // internal typedefs
1344 typedef typename detail::variant::make_variant_list<
1345 BOOST_VARIANT_ENUM_PARAMS(internal_T)
1346 >::type internal_types;
1348 private: // static precondition assertions
1351 // variant< type-sequence > syntax is not supported on this compiler!
1353 BOOST_MPL_ASSERT_NOT(( is_sequence_based_ ));
1355 #endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT workaround
1357 private: // helpers, for representation (below)
1359 typedef typename detail::variant::find_fallback_type<
1361 >::type fallback_type_result_;
1363 typedef typename fallback_type_result_::first
1364 fallback_type_index_;
1365 typedef typename fallback_type_result_::second
1368 struct has_fallback_type_
1370 is_same< fallback_type_, detail::variant::no_fallback_type >
1375 typedef has_fallback_type_
1376 never_uses_backup_flag;
1378 typedef typename detail::variant::make_storage<
1379 internal_types, never_uses_backup_flag
1382 #ifndef BOOST_NO_CXX11_NOEXCEPT
1383 typedef typename detail::variant::is_variant_move_noexcept_constructible<
1385 > variant_move_noexcept_constructible;
1387 typedef typename detail::variant::is_variant_move_noexcept_assignable<
1389 > variant_move_noexcept_assignable;
1393 private: // helpers, for representation (below)
1396 // * [0, size<internal_types>) indicates stack content
1397 // * [-size<internal_types>, 0) indicates pointer to heap backup
1399 // * then which() -> which_
1400 // * else which() -> -(which_ + 1)
1402 #if !defined(BOOST_VARIANT_MINIMIZE_SIZE)
1404 typedef int which_t;
1406 #else // defined(BOOST_VARIANT_MINIMIZE_SIZE)
1408 // [if O1_size available, then attempt which_t size optimization...]
1409 // [select signed char if fewer than SCHAR_MAX types, else signed int:]
1410 typedef typename mpl::eval_if<
1411 mpl::equal_to< mpl::O1_size<internal_types>, mpl::long_<-1> >
1412 , mpl::identity< int >
1414 mpl::less< mpl::O1_size<internal_types>, mpl::int_<SCHAR_MAX> >
1420 #endif // BOOST_VARIANT_MINIMIZE_SIZE switch
1422 // representation -- private when possible
1423 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1432 void indicate_which(int which_arg) BOOST_NOEXCEPT
1434 which_ = static_cast<which_t>( which_arg );
1437 void indicate_backup_which(int which_arg) BOOST_NOEXCEPT
1439 which_ = static_cast<which_t>( -(which_arg + 1) );
1442 private: // helpers, for queries (below)
1444 bool using_backup() const BOOST_NOEXCEPT
1451 int which() const BOOST_NOEXCEPT
1453 // If using heap backup...
1455 // ...then return adjusted which_:
1456 return -(which_ + 1);
1458 // Otherwise, return which_ directly:
1462 private: // helpers, for structors (below)
1465 : BOOST_VARIANT_AUX_INITIALIZER_T(
1466 recursive_enabled_types, recursive_enabled_T
1471 void destroy_content() BOOST_NOEXCEPT
1473 detail::variant::destroyer visitor;
1474 this->internal_apply_visitor(visitor);
1477 public: // structors
1479 ~variant() BOOST_NOEXCEPT
1485 #if !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130))
1486 BOOST_NOEXCEPT_IF(boost::has_nothrow_constructor<internal_T0>::value)
1490 #pragma warning( push )
1491 // behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized
1492 #pragma warning( disable : 4345 )
1495 // Compile error from here indicates that the first bound
1496 // type is not default-constructible, and so variant cannot
1497 // support its own default-construction.
1499 new( storage_.address() ) internal_T0();
1500 indicate_which(0); // zero is the index of the first bounded type
1502 #pragma warning( pop )
1506 private: // helpers, for structors, cont. (below)
1508 class convert_copy_into
1509 : public static_visitor<int>
1511 private: // representation
1515 public: // structors
1517 explicit convert_copy_into(void* storage) BOOST_NOEXCEPT
1522 public: // internal visitor interfaces (below)
1524 template <typename T>
1525 int internal_visit(T& operand, int) const
1528 // Compile error here indicates one of the source variant's types
1529 // cannot be unambiguously converted to the destination variant's
1530 // types (or that no conversion exists).
1532 return initializer::initialize(storage_, operand);
1535 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
1536 template <typename T>
1537 result_type internal_visit(const T& operand, int) const
1539 return initializer::initialize(storage_, operand);
1543 template <typename T>
1544 int internal_visit(boost::detail::reference_content<T>& operand, long) const
1546 return internal_visit( operand.get(), 1L );
1549 template <typename T>
1550 int internal_visit(const boost::detail::reference_content<T>& operand, long) const
1552 return internal_visit( operand.get(), 1L );
1555 template <typename T>
1556 int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
1558 return internal_visit( operand.get(), 1L );
1561 template <typename T>
1562 int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
1564 return internal_visit( operand.get(), 1L );
1567 template <typename T>
1568 int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1570 return internal_visit( operand.get(), 1L );
1573 template <typename T>
1574 int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
1576 return internal_visit( operand.get(), 1L );
1581 friend class convert_copy_into;
1583 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1584 class convert_move_into
1585 : public static_visitor<int>
1587 private: // representation
1591 public: // structors
1593 explicit convert_move_into(void* storage) BOOST_NOEXCEPT
1598 public: // internal visitor interfaces (below)
1600 template <typename T>
1601 int internal_visit(T& operand, int) const
1604 // Compile error here indicates one of the source variant's types
1605 // cannot be unambiguously converted to the destination variant's
1606 // types (or that no conversion exists).
1608 return initializer::initialize(storage_, detail::variant::move(operand) );
1611 template <typename T>
1612 int internal_visit(boost::detail::reference_content<T>& operand, long) const
1614 return internal_visit( operand.get(), 1L );
1617 template <typename T>
1618 int internal_visit(const boost::detail::reference_content<T>& operand, long) const
1620 return internal_visit( operand.get(), 1L );
1623 template <typename T>
1624 int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
1626 return internal_visit( operand.get(), 1L );
1629 template <typename T>
1630 int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
1632 return internal_visit( operand.get(), 1L );
1635 template <typename T>
1636 int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1638 return internal_visit( operand.get(), 1L );
1641 template <typename T>
1642 int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
1644 return internal_visit( operand.get(), 1L );
1648 friend class convert_move_into;
1651 private: // helpers, for structors, below
1653 template <typename T>
1654 void convert_construct(
1657 , mpl::false_ = mpl::false_() // is_foreign_variant
1661 // Compile error here indicates that the given type is not
1662 // unambiguously convertible to one of the variant's types
1663 // (or that no conversion exists).
1666 initializer::initialize(
1673 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1674 template <typename T>
1675 typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type convert_construct(
1678 , mpl::false_ = mpl::false_() // is_foreign_variant
1682 // Compile error here indicates that the given type is not
1683 // unambiguously convertible to one of the variant's types
1684 // (or that no conversion exists).
1687 initializer::initialize(
1689 , detail::variant::move(operand)
1695 template <typename Variant>
1696 void convert_construct(
1699 , mpl::true_// is_foreign_variant
1702 convert_copy_into visitor(storage_.address());
1704 operand.internal_apply_visitor(visitor)
1708 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1709 template <typename Variant>
1710 typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct(
1713 , mpl::true_// is_foreign_variant
1716 convert_move_into visitor(storage_.address());
1718 operand.internal_apply_visitor(visitor)
1723 template <typename Variant>
1724 void convert_construct_variant(Variant& operand)
1726 // [Determine if the given variant is itself a bounded type, or if its
1727 // content needs to be converted (i.e., it is a 'foreign' variant):]
1730 typedef typename mpl::find_if<
1738 typedef typename mpl::end<types>::type not_found;
1739 typedef typename is_same<
1741 >::type is_foreign_variant;
1743 // Convert construct from operand:
1746 , is_foreign_variant()
1750 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1751 template <typename Variant>
1752 typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct_variant(Variant&& operand)
1754 // [Determine if the given variant is itself a bounded type, or if its
1755 // content needs to be converted (i.e., it is a 'foreign' variant):]
1758 typedef typename mpl::find_if<
1766 typedef typename mpl::end<types>::type not_found;
1767 typedef typename is_same<
1769 >::type is_foreign_variant;
1771 // Convert move construct from operand:
1773 detail::variant::move(operand), 1L
1774 , is_foreign_variant()
1779 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1780 typename boost::enable_if<mpl::or_<
1781 boost::is_same<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>, variant>,
1782 boost::detail::variant::is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&, internal_types>
1783 > >::type convert_construct(
1784 boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1788 convert_construct_variant(operand);
1791 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1792 typename boost::enable_if<mpl::or_<
1793 boost::is_same<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>, variant>,
1794 boost::detail::variant::is_variant_constructible_from<const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&, internal_types>
1795 > >::type convert_construct(
1796 const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1800 convert_construct_variant(operand);
1803 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1804 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1805 typename boost::enable_if<mpl::or_<
1806 boost::is_same<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>, variant>,
1807 boost::detail::variant::is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&&, internal_types>
1808 > >::type convert_construct(
1809 boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&& operand
1813 convert_construct_variant( detail::variant::move(operand) );
1817 public: // structors, cont.
1819 template <typename T>
1820 variant(const T& operand,
1821 typename boost::enable_if<mpl::or_<
1823 mpl::not_< boost::is_same<T, variant> >,
1824 boost::detail::variant::is_variant_constructible_from<const T&, internal_types>
1826 boost::is_same<T, boost::recursive_variant_> > >::type* = 0)
1828 convert_construct(operand, 1L);
1831 template <typename T>
1834 , typename boost::enable_if<mpl::or_<
1836 mpl::not_< is_const<T> >,
1837 mpl::not_< boost::is_same<T, variant> >,
1838 boost::detail::variant::is_variant_constructible_from<T&, internal_types>
1840 boost::is_same<T, boost::recursive_variant_> > >::type* = 0
1843 convert_construct(operand, 1L);
1846 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1848 variant(T&& operand,
1849 typename boost::enable_if<mpl::or_<
1851 boost::is_rvalue_reference<T&&>,
1852 mpl::not_< boost::is_const<T> >,
1853 mpl::not_< boost::is_same<T, variant> >,
1854 boost::detail::variant::is_variant_constructible_from<T&&, internal_types>
1856 boost::is_same<T, boost::recursive_variant_> > >::type* = 0)
1858 convert_construct( detail::variant::move(operand), 1L);
1862 public: // structors, cont.
1864 // [MSVC6 requires copy constructor appear after template constructors]
1865 variant(const variant& operand)
1867 // Copy the value of operand into *this...
1868 detail::variant::copy_into visitor( storage_.address() );
1869 operand.internal_apply_visitor(visitor);
1871 // ...and activate the *this's primary storage on success:
1872 indicate_which(operand.which());
1875 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1876 variant(variant&& operand) BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value)
1878 // Move the value of operand into *this...
1879 detail::variant::move_into visitor( storage_.address() );
1880 operand.internal_apply_visitor(visitor);
1882 // ...and activate the *this's primary storage on success:
1883 indicate_which(operand.which());
1887 private: // helpers, for modifiers (below)
1889 # if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1890 template <typename Variant>
1891 friend class detail::variant::backup_assigner;
1896 // Internal visitor that "assigns" the visited value to the given variant
1897 // by appropriate destruction and copy-construction.
1901 : public static_visitor<>
1903 protected: // representation
1906 const int rhs_which_;
1908 public: // structors
1910 assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
1912 , rhs_which_(rhs_which)
1916 protected: // helpers, for internal visitor interface (below)
1918 template <typename RhsT, typename B1, typename B2>
1920 const RhsT& rhs_content
1921 , mpl::true_ // has_nothrow_copy
1922 , B1 // is_nothrow_move_constructible
1923 , B2 // has_fallback_type
1924 ) const BOOST_NOEXCEPT
1926 // Destroy lhs's content...
1927 lhs_.destroy_content(); // nothrow
1929 // ...copy rhs content into lhs's storage...
1930 new(lhs_.storage_.address())
1931 RhsT( rhs_content ); // nothrow
1933 // ...and indicate new content type:
1934 lhs_.indicate_which(rhs_which_); // nothrow
1937 template <typename RhsT, typename B>
1939 const RhsT& rhs_content
1940 , mpl::false_ // has_nothrow_copy
1941 , mpl::true_ // is_nothrow_move_constructible
1942 , B // has_fallback_type
1945 // Attempt to make a temporary copy (so as to move it below)...
1946 RhsT temp(rhs_content);
1948 // ...and upon success destroy lhs's content...
1949 lhs_.destroy_content(); // nothrow
1951 // ...move the temporary copy into lhs's storage...
1952 new(lhs_.storage_.address())
1953 RhsT( detail::variant::move(temp) ); // nothrow
1955 // ...and indicate new content type:
1956 lhs_.indicate_which(rhs_which_); // nothrow
1959 void construct_fallback() const BOOST_NOEXCEPT {
1960 // In case of failure, default-construct fallback type in lhs's storage...
1961 new (lhs_.storage_.address())
1962 fallback_type_; // nothrow
1964 // ...indicate construction of fallback type...
1965 lhs_.indicate_which(
1966 BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value
1970 template <typename RhsT>
1972 const RhsT& rhs_content
1973 , mpl::false_ // has_nothrow_copy
1974 , mpl::false_ // is_nothrow_move_constructible
1975 , mpl::true_ // has_fallback_type
1978 // Destroy lhs's content...
1979 lhs_.destroy_content(); // nothrow
1983 // ...and attempt to copy rhs's content into lhs's storage:
1984 new(lhs_.storage_.address())
1985 RhsT( rhs_content );
1989 construct_fallback();
1996 // In the event of success, indicate new content type:
1997 lhs_.indicate_which(rhs_which_); // nothrow
2000 template <typename RhsT>
2002 const RhsT& rhs_content
2003 , mpl::false_ // has_nothrow_copy
2004 , mpl::false_ // is_nothrow_move_constructible
2005 , mpl::false_ // has_fallback_type
2008 detail::variant::backup_assigner<wknd_self_t>
2009 visitor(lhs_, rhs_which_, rhs_content);
2010 lhs_.internal_apply_visitor(visitor);
2013 public: // internal visitor interfaces
2015 template <typename RhsT>
2016 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
2017 internal_visit(const RhsT& rhs_content, int) const
2019 typedef typename has_nothrow_copy<RhsT>::type
2021 typedef typename mpl::or_< // reduces compile-time
2023 , is_nothrow_move_constructible<RhsT>
2024 >::type nothrow_move_constructor;
2029 , nothrow_move_constructor()
2030 , has_fallback_type_()
2033 BOOST_VARIANT_AUX_RETURN_VOID;
2036 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
2038 // silence MSVC warning C4512: assignment operator could not be generated
2039 assigner& operator= (assigner const&);
2043 friend class assigner;
2045 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2046 // class move_assigner
2048 // Internal visitor that "move assigns" the visited value to the given variant
2049 // by appropriate destruction and move-construction.
2055 public: // structors
2057 move_assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
2058 : assigner(lhs, rhs_which)
2062 private: // helpers, for internal visitor interface (below)
2064 template <typename RhsT, typename B2>
2067 , mpl::true_ // has_nothrow_copy
2068 , mpl::false_ // is_nothrow_move_constructible
2069 , B2 // has_fallback_type
2070 ) const BOOST_NOEXCEPT
2072 assigner::assign_impl(rhs_content, mpl::true_(), mpl::false_(), B2());
2075 template <typename RhsT, typename B, typename B2>
2078 , B // has_nothrow_copy
2079 , mpl::true_ // is_nothrow_move_constructible
2080 , B2 // has_fallback_type
2081 ) const BOOST_NOEXCEPT
2083 // ...destroy lhs's content...
2084 assigner::lhs_.destroy_content(); // nothrow
2086 // ...move the rhs_content into lhs's storage...
2087 new(assigner::lhs_.storage_.address())
2088 RhsT( detail::variant::move(rhs_content) ); // nothrow
2090 // ...and indicate new content type:
2091 assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
2094 template <typename RhsT>
2097 , mpl::false_ // has_nothrow_copy
2098 , mpl::false_ // is_nothrow_move_constructible
2099 , mpl::true_ // has_fallback_type
2102 // Destroy lhs's content...
2103 assigner::lhs_.destroy_content(); // nothrow
2107 // ...and attempt to copy rhs's content into lhs's storage:
2108 new(assigner::lhs_.storage_.address())
2109 RhsT( detail::variant::move(rhs_content) );
2113 assigner::construct_fallback();
2120 // In the event of success, indicate new content type:
2121 assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
2124 template <typename RhsT>
2127 , mpl::false_ // has_nothrow_copy
2128 , mpl::false_ // is_nothrow_move_constructible
2129 , mpl::false_ // has_fallback_type
2132 assigner::assign_impl(rhs_content, mpl::false_(), mpl::false_(), mpl::false_());
2135 public: // internal visitor interfaces
2137 template <typename RhsT>
2138 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
2139 internal_visit(RhsT& rhs_content, int) const
2141 typedef typename is_nothrow_move_constructible<RhsT>::type
2142 nothrow_move_constructor;
2143 typedef typename mpl::or_< // reduces compile-time
2144 nothrow_move_constructor
2145 , has_nothrow_copy<RhsT>
2146 >::type nothrow_copy;
2151 , nothrow_move_constructor()
2152 , has_fallback_type_()
2155 BOOST_VARIANT_AUX_RETURN_VOID;
2158 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
2160 // silence MSVC warning C4512: assignment operator could not be generated
2161 move_assigner& operator= (move_assigner const&);
2165 friend class move_assigner;
2166 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2168 void variant_assign(const variant& rhs)
2170 // If the contained types are EXACTLY the same...
2171 if (which_ == rhs.which_)
2173 // ...then assign rhs's storage to lhs's content:
2174 detail::variant::assign_storage visitor(rhs.storage_.address());
2175 this->internal_apply_visitor(visitor);
2179 // Otherwise, perform general (copy-based) variant assignment:
2180 assigner visitor(*this, rhs.which());
2181 rhs.internal_apply_visitor(visitor);
2185 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2186 void variant_assign(variant&& rhs)
2188 // If the contained types are EXACTLY the same...
2189 if (which_ == rhs.which_)
2191 // ...then move rhs's storage to lhs's content:
2192 detail::variant::move_storage visitor(rhs.storage_.address());
2193 this->internal_apply_visitor(visitor);
2197 // Otherwise, perform general (move-based) variant assignment:
2198 move_assigner visitor(*this, rhs.which());
2199 rhs.internal_apply_visitor(visitor);
2202 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2204 private: // helpers, for modifiers (below)
2206 template <typename T>
2207 void assign(const T& rhs)
2209 // If direct T-to-T assignment is not possible...
2210 detail::variant::direct_assigner<T> direct_assign(rhs);
2211 if (this->apply_visitor(direct_assign) == false)
2213 // ...then convert rhs to variant and assign:
2215 // While potentially inefficient, the following construction of a
2216 // variant allows T as any type convertible to one of the bounded
2217 // types without excessive code redundancy.
2220 variant_assign( detail::variant::move(temp) );
2224 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2225 template <typename T>
2226 void move_assign(T&& rhs)
2228 // If direct T-to-T move assignment is not possible...
2229 detail::variant::direct_mover<T> direct_move(rhs);
2230 if (this->apply_visitor(direct_move) == false)
2232 // ...then convert rhs to variant and assign:
2234 // While potentially inefficient, the following construction of a
2235 // variant allows T as any type convertible to one of the bounded
2236 // types without excessive code redundancy.
2238 variant temp( detail::variant::move(rhs) );
2239 variant_assign( detail::variant::move(temp) );
2242 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2244 public: // modifiers
2246 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2248 typename boost::enable_if<
2250 boost::is_rvalue_reference<T&&>,
2251 mpl::not_< boost::is_const<T> >,
2252 boost::detail::variant::is_variant_constructible_from<T&&, internal_types>
2255 >::type operator=(T&& rhs)
2257 move_assign( detail::variant::move(rhs) );
2260 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2262 template <typename T>
2263 typename boost::enable_if<
2265 boost::is_same<T, variant>,
2266 boost::detail::variant::is_variant_constructible_from<const T&, internal_types>
2269 >::type operator=(const T& rhs)
2275 // [MSVC6 requires copy assign appear after templated operator=]
2276 variant& operator=(const variant& rhs)
2278 variant_assign(rhs);
2282 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
2283 variant& operator=(variant&& rhs)
2284 #if !defined(__GNUC__) || (__GNUC__ != 4) || (__GNUC_MINOR__ > 6) || defined(__clang__)
2285 BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value && variant_move_noexcept_assignable::type::value)
2288 variant_assign( detail::variant::move(rhs) );
2291 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
2293 void swap(variant& rhs)
2295 // If the contained types are the same...
2296 if (which() == rhs.which())
2298 // ...then swap the values directly:
2299 detail::variant::swap_with<variant> visitor(rhs);
2300 this->apply_visitor(visitor);
2304 // ...otherwise, perform general variant swap:
2305 variant tmp( detail::variant::move(rhs) );
2306 rhs = detail::variant::move(*this);
2307 *this = detail::variant::move(tmp);
2314 // NOTE: member which() defined above.
2317 bool empty() const BOOST_NOEXCEPT
2322 const boost::typeindex::type_info& type() const
2324 detail::variant::reflect visitor;
2325 return this->apply_visitor(visitor);
2328 public: // prevent comparison with foreign types
2330 template <typename U>
2331 void operator==(const U&) const
2333 BOOST_STATIC_ASSERT( false && sizeof(U) );
2336 template <typename U>
2337 void operator<(const U&) const
2339 BOOST_STATIC_ASSERT( false && sizeof(U) );
2342 template <typename U>
2343 void operator!=(const U&) const
2345 BOOST_STATIC_ASSERT( false && sizeof(U) );
2348 template <typename U>
2349 void operator>(const U&) const
2351 BOOST_STATIC_ASSERT( false && sizeof(U) );
2354 template <typename U>
2355 void operator<=(const U&) const
2357 BOOST_STATIC_ASSERT( false && sizeof(U) );
2360 template <typename U>
2361 void operator>=(const U&) const
2363 BOOST_STATIC_ASSERT( false && sizeof(U) );
2366 public: // comparison operators
2368 // [MSVC6 requires these operators appear after template operators]
2370 bool operator==(const variant& rhs) const
2372 if (this->which() != rhs.which())
2375 detail::variant::comparer<
2376 variant, detail::variant::equal_comp
2378 return rhs.apply_visitor(visitor);
2381 bool operator<(const variant& rhs) const
2384 // Dirk Schreib suggested this collating order.
2387 if (this->which() != rhs.which())
2388 return this->which() < rhs.which();
2390 detail::variant::comparer<
2391 variant, detail::variant::less_comp
2393 return rhs.apply_visitor(visitor);
2396 ///////////////////////////////////////////////////////////////////////////////
2397 // comparison operators != > <= >=
2398 inline bool operator!=(const variant& rhs) const
2400 return !(*this == rhs);
2403 inline bool operator>(const variant& rhs) const
2408 inline bool operator<=(const variant& rhs) const
2410 return !(*this > rhs);
2413 inline bool operator>=(const variant& rhs) const
2415 return !(*this < rhs);
2418 // helpers, for visitation support (below) -- private when possible
2419 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2421 template < BOOST_VARIANT_ENUM_PARAMS(typename U) >
2422 friend class variant;
2426 #else// defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2430 #endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2432 template <typename Visitor, typename VoidPtrCV>
2434 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2435 typename Visitor::result_type
2437 internal_apply_visitor_impl(
2444 typedef mpl::int_<0> first_which;
2445 typedef typename mpl::begin<internal_types>::type first_it;
2446 typedef typename mpl::end<internal_types>::type last_it;
2448 typedef detail::variant::visitation_impl_step<
2452 return detail::variant::visitation_impl(
2453 internal_which, logical_which
2454 , visitor, storage, mpl::false_()
2455 , never_uses_backup_flag()
2456 , static_cast<first_which*>(0), static_cast<first_step*>(0)
2460 template <typename Visitor>
2461 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2462 typename Visitor::result_type
2464 internal_apply_visitor(Visitor& visitor)
2466 return internal_apply_visitor_impl(
2467 which_, which(), visitor, storage_.address()
2471 template <typename Visitor>
2472 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2473 typename Visitor::result_type
2475 internal_apply_visitor(Visitor& visitor) const
2477 return internal_apply_visitor_impl(
2478 which_, which(), visitor, storage_.address()
2482 public: // visitation support
2484 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
2486 template <typename Visitor>
2487 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2488 typename Visitor::result_type
2490 apply_visitor(Visitor& visitor) &&
2492 detail::variant::invoke_visitor<Visitor, true> invoker(visitor);
2493 return this->internal_apply_visitor(invoker);
2496 template <typename Visitor>
2497 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2498 typename Visitor::result_type
2500 apply_visitor(Visitor& visitor) const&&
2502 detail::variant::invoke_visitor<Visitor, true> invoker(visitor);
2503 return this->internal_apply_visitor(invoker);
2508 template <typename Visitor>
2509 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2510 typename Visitor::result_type
2512 apply_visitor(Visitor& visitor)
2513 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
2517 detail::variant::invoke_visitor<Visitor, false> invoker(visitor);
2518 return this->internal_apply_visitor(invoker);
2521 template <typename Visitor>
2522 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
2523 typename Visitor::result_type
2525 apply_visitor(Visitor& visitor) const
2526 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
2530 detail::variant::invoke_visitor<Visitor, false> invoker(visitor);
2531 return this->internal_apply_visitor(invoker);
2536 ///////////////////////////////////////////////////////////////////////////////
2537 // metafunction make_variant_over
2539 // See docs and boost/variant/variant_fwd.hpp for more information.
2541 template <typename Types>
2542 struct make_variant_over
2544 private: // precondition assertions
2546 BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value ));
2547 typedef typename boost::mpl::insert_range<
2549 , boost::mpl::end< boost::mpl::list<> >::type
2551 >::type copied_sequence_t;
2553 public: // metafunction result
2556 detail::variant::over_sequence<copied_sequence_t>
2561 ///////////////////////////////////////////////////////////////////////////////
2562 // function template swap
2564 // Swaps two variants of the same type (i.e., identical specification).
2566 template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
2568 variant< BOOST_VARIANT_ENUM_PARAMS(T) >& lhs
2569 , variant< BOOST_VARIANT_ENUM_PARAMS(T) >& rhs
2575 } // namespace boost
2577 // implementation additions
2579 #if !defined(BOOST_NO_IOSTREAM)
2580 #include <boost/variant/detail/variant_io.hpp>
2581 #endif // BOOST_NO_IOSTREAM
2583 #endif // BOOST_VARIANT_VARIANT_HPP