Attempt to represent the S^2->S^3 header reorganisation as a series of "hg rename" operations
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
7 // Eric Friedman, Itay Maman
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 * © Portions copyright (c) 2006-2007 Nokia Corporation. All rights reserved.
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
23 #include <typeinfo> // for typeid, std::type_info
25 #include "boost/variant/detail/config.hpp"
26 #include "boost/mpl/aux_/config/eti.hpp"
27 #include "boost/mpl/aux_/value_wknd.hpp"
29 #include "boost/variant/variant_fwd.hpp"
30 #include "boost/variant/detail/backup_holder.hpp"
31 #include "boost/variant/detail/enable_recursive_fwd.hpp"
32 #include "boost/variant/detail/forced_return.hpp"
33 #include "boost/variant/detail/initializer.hpp"
34 #include "boost/variant/detail/make_variant_list.hpp"
35 #include "boost/variant/detail/over_sequence.hpp"
36 #include "boost/variant/detail/visitation_impl.hpp"
38 #include "boost/variant/detail/generic_result_type.hpp"
39 #include "boost/variant/detail/has_nothrow_move.hpp"
40 #include "boost/variant/detail/move.hpp"
42 #include "boost/detail/reference_content.hpp"
43 #include "boost/aligned_storage.hpp"
44 #include "boost/blank.hpp"
45 #include "boost/static_assert.hpp"
46 #include "boost/preprocessor/cat.hpp"
47 #include "boost/preprocessor/repeat.hpp"
48 #include "boost/type_traits/alignment_of.hpp"
49 #include "boost/type_traits/add_const.hpp"
50 #include "boost/type_traits/has_nothrow_constructor.hpp"
51 #include "boost/type_traits/has_nothrow_copy.hpp"
52 #include "boost/type_traits/is_const.hpp"
53 #include "boost/type_traits/is_same.hpp"
54 #include "boost/utility/enable_if.hpp"
55 #include "boost/variant/recursive_wrapper_fwd.hpp"
56 #include "boost/variant/static_visitor.hpp"
58 #include "boost/mpl/eval_if.hpp"
59 #include "boost/mpl/begin_end.hpp"
60 #include "boost/mpl/bool.hpp"
61 #include "boost/mpl/empty.hpp"
62 #include "boost/mpl/find_if.hpp"
63 #include "boost/mpl/front.hpp"
64 #include "boost/mpl/identity.hpp"
65 #include "boost/mpl/if.hpp"
66 #include "boost/mpl/int.hpp"
67 #include "boost/mpl/is_sequence.hpp"
68 #include "boost/mpl/iterator_range.hpp"
69 #include "boost/mpl/iter_fold_if.hpp"
70 #include "boost/mpl/logical.hpp"
71 #include "boost/mpl/max_element.hpp"
72 #include "boost/mpl/next.hpp"
73 #include "boost/mpl/deref.hpp"
74 #include "boost/mpl/pair.hpp"
75 #include "boost/mpl/protect.hpp"
76 #include "boost/mpl/push_front.hpp"
77 #include "boost/mpl/same_as.hpp"
78 #include "boost/mpl/size_t.hpp"
79 #include "boost/mpl/sizeof.hpp"
80 #include "boost/mpl/transform.hpp"
81 #include "boost/mpl/assert.hpp"
83 ///////////////////////////////////////////////////////////////////////////////
84 // Implementation Macros:
86 // BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
87 // Defined in boost/variant/detail/visitation_impl.hpp.
89 // BOOST_VARIANT_MINIMIZE_SIZE
90 // When #defined, implementation employs all known means to minimize the
91 // size of variant obje cts. However, often unsuccessful due to alignment
92 // issues, and potentially harmful to runtime speed, so not enabled by
93 // default. (TODO: Investigate further.)
95 #if defined(BOOST_VARIANT_MINIMIZE_SIZE)
96 # include <climits> // for SCHAR_MAX
97 # include "boost/mpl/eval_if.hpp"
98 # include "boost/mpl/equal_to.hpp"
99 # include "boost/mpl/identity.hpp"
100 # include "boost/mpl/int.hpp"
101 # include "boost/mpl/if.hpp"
102 # include "boost/mpl/less.hpp"
103 # include "boost/mpl/long.hpp"
104 # include "boost/mpl/O1_size.hpp"
110 namespace detail { namespace variant {
112 ///////////////////////////////////////////////////////////////////////////////
113 // (detail) metafunction max_value
115 // Finds the maximum value of the unary metafunction F over Sequence.
117 template <typename Sequence, typename F>
120 private: // helpers, for metafunction result (below)
122 typedef typename mpl::transform1<Sequence, F>::type transformed_;
123 typedef typename mpl::max_element<transformed_
127 public: // metafunction result
129 typedef typename mpl::deref<max_it>::type
134 ///////////////////////////////////////////////////////////////////////////////
135 // (detail) metafunction find_fallback_type
137 // Provides a fallback (i.e., nothrow default-constructible) type from the
138 // specified sequence, or no_fallback_type if not found.
140 // This implementation is designed to prefer boost::blank over other potential
141 // fallback types, regardless of its position in the specified sequence.
144 class no_fallback_type;
146 struct find_fallback_type_pred
148 template <typename Iterator>
152 typedef typename mpl::deref<Iterator>::type t_;
155 typedef mpl::not_< has_nothrow_constructor<t_> > type;
159 template <typename Types>
160 struct find_fallback_type
162 private: // helpers, for metafunction result (below)
164 typedef typename mpl::end<Types>::type end_it;
166 // [Find the first suitable fallback type...]
168 typedef typename mpl::iter_fold_if<
170 , mpl::int_<0>, mpl::protect< mpl::next<> >
171 , mpl::protect< find_fallback_type_pred >
172 >::type first_result_;
174 typedef typename first_result_::first first_result_index;
175 typedef typename first_result_::second first_result_it;
177 // [...now search the rest of the sequence for boost::blank...]
179 typedef typename mpl::iter_fold_if<
180 mpl::iterator_range< first_result_it,end_it >
181 , first_result_index, mpl::protect< mpl::next<> >
182 , mpl::protect< mpl::not_same_as<boost::blank> >
183 >::type second_result_;
185 typedef typename second_result_::second second_result_it;
187 public: // metafunction result
189 // [...and return the results of the search:]
190 typedef typename mpl::eval_if<
191 is_same< second_result_it,end_it >
193 is_same< first_result_it,end_it >
194 , mpl::pair< no_fallback_type,no_fallback_type >
197 , mpl::identity< second_result_ >
202 #if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
205 struct find_fallback_type<int>
207 typedef mpl::pair< no_fallback_type,no_fallback_type > type;
210 #endif // BOOST_MPL_CFG_MSVC_60_ETI_BUG workaround
212 ///////////////////////////////////////////////////////////////////////////////
213 // (detail) metafunction make_storage
215 // Provides an aligned storage type capable of holding any of the types
216 // specified in the given type-sequence.
219 template <typename Types, typename NeverUsesBackupFlag>
222 private: // helpers, for metafunction result (below)
224 typedef typename mpl::eval_if<
226 , mpl::identity< Types >
228 Types, backup_holder<void*>
232 typedef typename max_value<
233 types, mpl::sizeof_<mpl::_1>
236 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
238 typedef typename max_value<
239 types, alignment_of<mpl::_1>
240 >::type max_alignment;
244 // temporary workaround -- use maximal alignment
245 typedef mpl::size_t< -1 > max_alignment;
247 #endif // borland workaround
249 public: // metafunction result
251 #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
253 typedef ::boost::aligned_storage<
254 BOOST_MPL_AUX_VALUE_WKND(max_size)::value
255 , BOOST_MPL_AUX_VALUE_WKND(max_alignment)::value
258 #else // MSVC7 and below
260 BOOST_STATIC_CONSTANT(std::size_t, msvc_max_size_c = max_size::value);
261 BOOST_STATIC_CONSTANT(std::size_t, msvc_max_alignment_c = max_alignment::value);
263 typedef ::boost::aligned_storage<
265 , msvc_max_alignment_c
268 #endif // MSVC workaround
272 #if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
275 struct make_storage<int,int>
280 #endif // BOOST_MPL_CFG_MSVC_60_ETI_BUG workaround
282 ///////////////////////////////////////////////////////////////////////////////
283 // (detail) class destroyer
285 // Internal visitor that destroys the value it visits.
288 : public static_visitor<>
290 public: // visitor interfaces
292 template <typename T>
293 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
294 internal_visit(T& operand, int) const
298 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
299 operand; // suppresses warnings
302 BOOST_VARIANT_AUX_RETURN_VOID;
307 ///////////////////////////////////////////////////////////////////////////////
308 // (detail) class template known_get
310 // Visitor that returns a reference to content of the specified type.
312 // Precondition: visited variant MUST contain logical content of type T.
314 template <typename T>
316 : public static_visitor<T&>
319 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
321 public: // visitor interface
323 T& operator()(T& operand) const
328 template <typename U>
329 T& operator()(U&) const
331 // logical error to be here: see precondition above
333 return ::boost::detail::variant::forced_return< T& >();
338 private: // helpers, for visitor interface (below)
340 T& execute(T& operand, mpl::true_) const
345 template <typename U>
346 T& execute(U& operand, mpl::false_) const
348 // logical error to be here: see precondition above
350 return ::boost::detail::variant::forced_return< T& >();
353 public: // visitor interface
355 template <typename U>
356 T& operator()(U& operand) const
358 typedef typename is_same< U,T >::type
361 return execute(operand, U_is_T());
364 #endif // MSVC6 workaround
368 ///////////////////////////////////////////////////////////////////////////////
369 // (detail) class copy_into
371 // Internal visitor that copies the value it visits into the given buffer.
374 : public static_visitor<>
376 private: // representation
382 explicit copy_into(void* storage)
387 public: // internal visitor interface
389 template <typename T>
390 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
391 internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
393 new(storage_) T( operand.get() );
394 BOOST_VARIANT_AUX_RETURN_VOID;
397 template <typename T>
398 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
399 internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
401 new(storage_) T( operand.get() );
402 BOOST_VARIANT_AUX_RETURN_VOID;
405 template <typename T>
406 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
407 internal_visit(const T& operand, int) const
409 new(storage_) T(operand);
410 BOOST_VARIANT_AUX_RETURN_VOID;
415 ///////////////////////////////////////////////////////////////////////////////
416 // (detail) class assign_storage
418 // Internal visitor that assigns the given storage (which must be a
419 // constructed value of the same type) to the value it visits.
421 struct assign_storage
422 : public static_visitor<>
424 private: // representation
426 const void* rhs_storage_;
430 explicit assign_storage(const void* rhs_storage)
431 : rhs_storage_(rhs_storage)
435 public: // internal visitor interfaces
437 template <typename T>
438 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
439 internal_visit(backup_holder<T>& lhs_content, long) const
442 = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
443 BOOST_VARIANT_AUX_RETURN_VOID;
446 template <typename T>
447 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
448 internal_visit(const backup_holder<T>& lhs_content, long) const
451 = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
452 BOOST_VARIANT_AUX_RETURN_VOID;
455 template <typename T>
456 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
457 internal_visit(T& lhs_content, int) const
460 // Compile error here indicates one of variant's bounded types does
461 // not meet the requirements of the Assignable concept. Thus,
462 // variant is not Assignable.
464 // Hint: Are any of the bounded types const-qualified or references?
466 lhs_content = *static_cast< const T* >(rhs_storage_);
467 BOOST_VARIANT_AUX_RETURN_VOID;
472 ///////////////////////////////////////////////////////////////////////////////
473 // (detail) class direct_assigner
475 // Generic static visitor that: if and only if the visited value is of the
476 // specified type, assigns the given value to the visited value and returns
477 // true; else returns false.
479 template <typename T>
480 class direct_assigner
481 : public static_visitor<bool>
483 private: // representation
489 explicit direct_assigner(T& rhs)
494 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
496 public: // visitor interface
498 bool operator()(T& lhs)
504 template <typename U>
512 private: // helpers, for visitor interface (below)
514 bool execute(T& lhs, mpl::true_)
520 template <typename U>
521 bool execute(U&, mpl::false_)
526 public: // visitor interface
528 template <typename U>
529 bool operator()(U& lhs)
531 typedef typename is_same<U,T>::type U_is_T;
532 return execute(lhs, U_is_T());
535 #endif // MSVC6 workaround
539 ///////////////////////////////////////////////////////////////////////////////
540 // (detail) class backup_assigner
542 // Internal visitor that "assigns" the given value to the visited value,
543 // using backup to recover if the destroy-copy sequence fails.
545 // NOTE: This needs to be a friend of variant, as it needs access to
546 // indicate_which, indicate_backup_which, etc.
548 template <typename Variant, typename RhsT>
549 class backup_assigner
550 : public static_visitor<>
552 private: // representation
556 const RhsT& rhs_content_;
560 backup_assigner(Variant& lhs, int rhs_which, const RhsT& rhs_content)
562 , rhs_which_(rhs_which)
563 , rhs_content_(rhs_content)
567 private: // helpers, for visitor interface (below)
569 template <typename LhsT>
570 void backup_assign_impl(
572 , mpl::true_// has_nothrow_move
575 // Move lhs content to backup...
576 LhsT backup_lhs_content(
577 ::boost::detail::variant::move(lhs_content)
580 // ...destroy lhs content...
581 lhs_content.~LhsT(); // nothrow
585 // ...and attempt to copy rhs content into lhs storage:
586 new(lhs_.storage_.address()) RhsT(rhs_content_);
590 // In case of failure, restore backup content to lhs storage...
591 new(lhs_.storage_.address())
593 ::boost::detail::variant::move(backup_lhs_content)
600 // In case of success, indicate new content type:
601 lhs_.indicate_which(rhs_which_); // nothrow
604 template <typename LhsT>
605 void backup_assign_impl(
607 , mpl::false_// has_nothrow_move
610 // Backup lhs content...
611 LhsT* backup_lhs_ptr = new LhsT(lhs_content);
613 // ...destroy lhs content...
614 lhs_content.~LhsT(); // nothrow
618 // ...and attempt to copy rhs content into lhs storage:
619 new(lhs_.storage_.address()) RhsT(rhs_content_);
623 // In case of failure, copy backup pointer to lhs storage...
624 new(lhs_.storage_.address())
625 backup_holder<LhsT>( backup_lhs_ptr ); // nothrow
627 // ...indicate now using backup...
628 lhs_.indicate_backup_which( lhs_.which() ); // nothrow
634 // In case of success, indicate new content type...
635 lhs_.indicate_which(rhs_which_); // nothrow
637 // ...and delete backup:
638 delete backup_lhs_ptr; // nothrow
641 public: // visitor interface
643 template <typename LhsT>
644 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
645 internal_visit(LhsT& lhs_content, int)
647 typedef typename has_nothrow_move_constructor<LhsT>::type
650 backup_assign_impl( lhs_content, nothrow_move() );
652 BOOST_VARIANT_AUX_RETURN_VOID;
657 ///////////////////////////////////////////////////////////////////////////////
658 // (detail) class swap_with
660 // Visitor that swaps visited value with content of given variant.
662 // Precondition: Given variant MUST have same logical type as visited value.
664 template <typename Variant>
666 : public static_visitor<>
668 private: // representation
674 explicit swap_with(Variant& toswap)
679 public: // internal visitor interfaces
681 template <typename T>
682 void operator()(T& operand) const
684 // Since the precondition ensures types are same, get T...
686 T& other = toswap_.apply_visitor(getter);
689 ::boost::detail::variant::move_swap( operand, other );
694 ///////////////////////////////////////////////////////////////////////////////
695 // (detail) class reflect
697 // Generic static visitor that performs a typeid on the value it visits.
700 : public static_visitor<const std::type_info&>
702 public: // visitor interfaces
704 template <typename T>
705 const std::type_info& operator()(const T&) const
712 ///////////////////////////////////////////////////////////////////////////////
713 // (detail) class comparer
715 // Generic static visitor that compares the content of the given lhs variant
716 // with the visited rhs content using Comp.
718 // Precondition: lhs.which() == rhs.which()
720 template <typename Variant, typename Comp>
722 : public static_visitor<bool>
724 private: // representation
730 explicit comparer(const Variant& lhs)
735 public: // visitor interfaces
737 template <typename T>
738 bool operator()(const T& rhs_content) const
740 // Since the precondition ensures lhs and rhs types are same, get T...
741 known_get<const T> getter;
742 const T& lhs_content = lhs_.apply_visitor(getter);
744 // ...and compare lhs and rhs contents:
745 return Comp()(lhs_content, rhs_content);
750 ///////////////////////////////////////////////////////////////////////////////
751 // (detail) class equal_comp
753 // Generic function object compares lhs with rhs using operator==.
757 template <typename T>
758 bool operator()(const T& lhs, const T& rhs) const
764 ///////////////////////////////////////////////////////////////////////////////
765 // (detail) class less_comp
767 // Generic function object compares lhs with rhs using operator<.
771 template <typename T>
772 bool operator()(const T& lhs, const T& rhs) const
778 ///////////////////////////////////////////////////////////////////////////////
779 // (detail) class template invoke_visitor
781 // Internal visitor that invokes the given visitor using:
782 // * for wrappers (e.g., recursive_wrapper), the wrapper's held value.
783 // * for all other values, the value itself.
785 template <typename Visitor>
788 private: // representation
792 public: // visitor typedefs
794 typedef typename Visitor::result_type
799 explicit invoke_visitor(Visitor& visitor)
804 #if !defined(BOOST_NO_VOID_RETURNS)
806 public: // internal visitor interfaces
808 template <typename T>
809 result_type internal_visit(T& operand, int)
811 return visitor_(operand);
814 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
815 template <typename T>
816 result_type internal_visit(const T& operand, int)
818 return visitor_(operand);
822 #else // defined(BOOST_NO_VOID_RETURNS)
824 private: // helpers, for internal visitor interfaces (below)
826 template <typename T>
827 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
828 visit_impl(T& operand, mpl::false_)
830 return visitor_(operand);
833 template <typename T>
834 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
835 visit_impl(T& operand, mpl::true_)
838 BOOST_VARIANT_AUX_RETURN_VOID;
841 public: // internal visitor interfaces
843 template <typename T>
844 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
845 internal_visit(T& operand, int)
847 typedef typename is_same<result_type, void>::type
848 has_void_result_type;
850 return visit_impl(operand, has_void_result_type());
853 #endif // BOOST_NO_VOID_RETURNS) workaround
855 public: // internal visitor interfaces, cont.
857 template <typename T>
858 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
859 internal_visit(boost::recursive_wrapper<T>& operand, long)
861 return internal_visit( operand.get(), 1L );
864 template <typename T>
865 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
866 internal_visit(const boost::recursive_wrapper<T>& operand, long)
868 return internal_visit( operand.get(), 1L );
871 template <typename T>
872 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
873 internal_visit(boost::detail::reference_content<T>& operand, long)
875 return internal_visit( operand.get(), 1L );
878 template <typename T>
879 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
880 internal_visit(const boost::detail::reference_content<T>& operand, long)
882 return internal_visit( operand.get(), 1L );
885 template <typename T>
886 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
887 internal_visit(boost::detail::variant::backup_holder<T>& operand, long)
889 return internal_visit( operand.get(), 1L );
892 template <typename T>
893 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
894 internal_visit(const boost::detail::variant::backup_holder<T>& operand, long)
896 return internal_visit( operand.get(), 1L );
901 }} // namespace detail::variant
903 ///////////////////////////////////////////////////////////////////////////////
904 // class template variant (concept inspired by Andrei Alexandrescu)
906 // See docs and boost/variant/variant_fwd.hpp for more information.
910 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)
914 private: // helpers, for typedefs (below)
916 typedef variant wknd_self_t;
919 : detail::variant::is_recursive_flag<T0_>
923 typedef typename mpl::eval_if<
926 , mpl::identity< T0_ >
927 >::type unwrapped_T0_;
929 struct is_sequence_based_
930 : detail::variant::is_over_sequence<unwrapped_T0_>
934 #if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
936 private: // helpers, for typedefs (below)
938 typedef typename mpl::eval_if<
940 , unwrapped_T0_ // over_sequence<...>::type
941 , detail::variant::make_variant_list<
943 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
945 >::type specified_types;
947 BOOST_STATIC_ASSERT((
948 ::boost::mpl::not_< mpl::empty<specified_types> >::value
951 typedef typename mpl::eval_if<
956 detail::variant::quoted_enable_recursive<wknd_self_t>
959 , mpl::identity< specified_types >
960 >::type recursive_enabled_types;
962 public: // public typedefs
964 typedef typename mpl::transform<
965 recursive_enabled_types
966 , unwrap_recursive<mpl::_1>
969 private: // internal typedefs
971 typedef typename mpl::transform<
972 recursive_enabled_types
973 , mpl::protect< detail::make_reference_content<> >
974 >::type internal_types;
976 typedef typename mpl::front<
980 #else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
982 private: // helpers, for typedefs (below)
984 typedef unwrapped_T0_ T0;
986 #define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
987 typedef typename mpl::eval_if< \
989 , detail::variant::enable_recursive< \
993 , mpl::identity< BOOST_PP_CAT(T,N) > \
994 >::type BOOST_PP_CAT(recursive_enabled_T,N); \
998 BOOST_VARIANT_LIMIT_TYPES
999 , BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1003 #undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1005 #define BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS(z,N,_) \
1006 typedef typename unwrap_recursive< \
1007 BOOST_PP_CAT(recursive_enabled_T,N) \
1008 >::type BOOST_PP_CAT(public_T,N); \
1012 BOOST_VARIANT_LIMIT_TYPES
1013 , BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1017 #undef BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1019 public: // public typedefs
1021 typedef typename detail::variant::make_variant_list<
1022 BOOST_VARIANT_ENUM_PARAMS(public_T)
1025 private: // helpers, for internal typedefs (below)
1027 #define BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS(z,N,_) \
1028 typedef detail::make_reference_content< \
1029 BOOST_PP_CAT(recursive_enabled_T,N) \
1030 >::type BOOST_PP_CAT(internal_T,N); \
1034 BOOST_VARIANT_LIMIT_TYPES
1035 , BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1039 #undef BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1041 private: // internal typedefs
1043 typedef typename detail::variant::make_variant_list<
1044 BOOST_VARIANT_ENUM_PARAMS(internal_T)
1045 >::type internal_types;
1047 private: // static precondition assertions
1050 // variant< type-sequence > syntax is not supported on this compiler!
1052 BOOST_MPL_ASSERT_NOT(( is_sequence_based_ ));
1054 #endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT workaround
1056 private: // helpers, for representation (below)
1058 typedef typename detail::variant::find_fallback_type<
1060 >::type fallback_type_result_;
1062 typedef typename fallback_type_result_::first
1063 fallback_type_index_;
1064 typedef typename fallback_type_result_::second
1067 struct has_fallback_type_
1069 is_same< fallback_type_, detail::variant::no_fallback_type >
1074 typedef has_fallback_type_
1075 never_uses_backup_flag;
1077 typedef typename detail::variant::make_storage<
1078 internal_types, never_uses_backup_flag
1081 private: // helpers, for representation (below)
1084 // * [0, size<internal_types>) indicates stack content
1085 // * [-size<internal_types>, 0) indicates pointer to heap backup
1087 // * then which() -> which_
1088 // * else which() -> -(which_ + 1)
1090 #if !defined(BOOST_VARIANT_MINIMIZE_SIZE)
1092 typedef int which_t;
1094 #else // defined(BOOST_VARIANT_MINIMIZE_SIZE)
1096 // [if O1_size available, then attempt which_t size optimization...]
1097 // [select signed char if fewer than SCHAR_MAX types, else signed int:]
1098 typedef typename mpl::eval_if<
1099 mpl::equal_to< mpl::O1_size<internal_types>, mpl::long_<-1> >
1100 , mpl::identity< int >
1102 mpl::less< mpl::O1_size<internal_types>, mpl::int_<SCHAR_MAX> >
1108 #endif // BOOST_VARIANT_MINIMIZE_SIZE switch
1110 // representation -- private when possible
1111 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1120 void indicate_which(int which)
1122 which_ = static_cast<which_t>( which );
1125 void indicate_backup_which(int which)
1127 which_ = static_cast<which_t>( -(which + 1) );
1130 private: // helpers, for queries (below)
1132 bool using_backup() const
1141 // If using heap backup...
1143 // ...then return adjusted which_:
1144 return -(which_ + 1);
1146 // Otherwise, return which_ directly:
1150 private: // helpers, for structors (below)
1153 : BOOST_VARIANT_AUX_INITIALIZER_T(
1154 recursive_enabled_types, recursive_enabled_T
1159 void destroy_content()
1161 detail::variant::destroyer visitor;
1162 this->internal_apply_visitor(visitor);
1165 public: // structors
1175 // Compile error from here indicates that the first bound
1176 // type is not default-constructible, and so variant cannot
1177 // support its own default-construction.
1179 new( storage_.address() ) internal_T0();
1180 indicate_which(0); // zero is the index of the first bounded type
1183 private: // helpers, for structors, cont. (below)
1185 class convert_copy_into
1186 : public static_visitor<int>
1188 private: // representation
1192 public: // structors
1194 explicit convert_copy_into(void* storage)
1199 public: // internal visitor interfaces (below)
1201 template <typename T>
1202 int internal_visit(T& operand, int) const
1205 // Compile error here indicates one of the source variant's types
1206 // cannot be unambiguously converted to the destination variant's
1207 // types (or that no conversion exists).
1209 return initializer::initialize(storage_, operand);
1212 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
1213 template <typename T>
1214 result_type internal_visit(const T& operand, int) const
1216 return initializer::initialize(storage_, operand);
1220 template <typename T>
1221 int internal_visit(boost::detail::reference_content<T>& operand, long) const
1223 return internal_visit( operand.get(), 1L );
1226 template <typename T>
1227 int internal_visit(const boost::detail::reference_content<T>& operand, long) const
1229 return internal_visit( operand.get(), 1L );
1232 template <typename T>
1233 int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
1235 return internal_visit( operand.get(), 1L );
1238 template <typename T>
1239 int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
1241 return internal_visit( operand.get(), 1L );
1244 template <typename T>
1245 int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1247 return internal_visit( operand.get(), 1L );
1250 template <typename T>
1251 int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
1253 return internal_visit( operand.get(), 1L );
1258 friend class convert_copy_into;
1260 private: // helpers, for structors, below
1262 template <typename T>
1263 void convert_construct(
1266 , mpl::false_ = mpl::false_() // is_foreign_variant
1270 // Compile error here indicates that the given type is not
1271 // unambiguously convertible to one of the variant's types
1272 // (or that no conversion exists).
1275 initializer::initialize(
1282 template <typename Variant>
1283 void convert_construct(
1286 , mpl::true_// is_foreign_variant
1289 convert_copy_into visitor(storage_.address());
1291 operand.internal_apply_visitor(visitor)
1295 template <typename Variant>
1296 void convert_construct_variant(Variant& operand)
1298 // [Determine if the given variant is itself a bounded type, or if its
1299 // content needs to be converted (i.e., it is a 'foreign' variant):]
1302 typedef typename mpl::find_if<
1310 typedef typename mpl::end<types>::type not_found;
1311 typedef typename is_same<
1313 >::type is_foreign_variant;
1315 // Convert construct from operand:
1318 , is_foreign_variant()
1322 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1323 void convert_construct(
1324 boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1328 convert_construct_variant(operand);
1331 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1332 void convert_construct(
1333 const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1337 convert_construct_variant(operand);
1340 public: // structors, cont.
1342 #if !defined(BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING)
1344 template <typename T>
1345 variant(const T& operand)
1347 convert_construct(operand, 1L);
1350 template <typename T>
1353 convert_construct(operand, 1L);
1356 #elif defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND)
1358 // For compilers that cannot distinguish between T& and const T& in
1359 // template constructors, but do fully support SFINAE, we can workaround:
1361 template <typename T>
1362 variant(const T& operand)
1364 convert_construct(operand, 1L);
1367 template <typename T>
1370 , typename enable_if<
1371 mpl::not_< is_const<T> >
1376 convert_construct(operand, 1L);
1379 #else // !defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND)
1381 // For compilers that cannot distinguish between T& and const T& in
1382 // template constructors, and do NOT support SFINAE, we can't workaround:
1384 template <typename T>
1385 variant(const T& operand)
1387 convert_construct(operand, 1L);
1390 #endif // BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING workarounds
1392 public: // structors, cont.
1394 // [MSVC6 requires copy constructor appear after template constructors]
1395 variant(const variant& operand)
1397 // Copy the value of operand into *this...
1398 detail::variant::copy_into visitor( storage_.address() );
1399 operand.internal_apply_visitor(visitor);
1401 // ...and activate the *this's primary storage on success:
1402 indicate_which(operand.which());
1405 private: // helpers, for modifiers (below)
1407 # if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1408 template <typename Variant, typename RhsT>
1409 friend class detail::variant::backup_assigner;
1414 // Internal visitor that "assigns" the visited value to the given variant
1415 // by appropriate destruction and copy-construction.
1419 : public static_visitor<>
1421 private: // representation
1426 public: // structors
1428 assigner(variant& lhs, int rhs_which)
1430 , rhs_which_(rhs_which)
1434 private: // helpers, for internal visitor interface (below)
1436 template <typename RhsT, typename B1, typename B2>
1438 const RhsT& rhs_content
1439 , mpl::true_// has_nothrow_copy
1440 , B1// has_nothrow_move_constructor
1441 , B2// has_fallback_type
1444 // Destroy lhs's content...
1445 lhs_.destroy_content(); // nothrow
1447 // ...copy rhs content into lhs's storage...
1448 new(lhs_.storage_.address())
1449 RhsT( rhs_content ); // nothrow
1451 // ...and indicate new content type:
1452 lhs_.indicate_which(rhs_which_); // nothrow
1455 template <typename RhsT, typename B>
1457 const RhsT& rhs_content
1458 , mpl::false_// has_nothrow_copy
1459 , mpl::true_// has_nothrow_move_constructor
1460 , B// has_fallback_type
1463 // Attempt to make a temporary copy (so as to move it below)...
1464 RhsT temp(rhs_content);
1466 // ...and upon success destroy lhs's content...
1467 lhs_.destroy_content(); // nothrow
1469 // ...move the temporary copy into lhs's storage...
1470 new(lhs_.storage_.address())
1471 RhsT( detail::variant::move(temp) ); // nothrow
1473 // ...and indicate new content type:
1474 lhs_.indicate_which(rhs_which_); // nothrow
1477 template <typename RhsT>
1479 const RhsT& rhs_content
1480 , mpl::false_// has_nothrow_copy
1481 , mpl::false_// has_nothrow_move_constructor
1482 , mpl::true_// has_fallback_type
1485 // Destroy lhs's content...
1486 lhs_.destroy_content(); // nothrow
1490 // ...and attempt to copy rhs's content into lhs's storage:
1491 new(lhs_.storage_.address())
1492 RhsT( rhs_content );
1496 // In case of failure, default-construct fallback type in lhs's storage...
1497 new (lhs_.storage_.address())
1498 fallback_type_; // nothrow
1500 // ...indicate construction of fallback type...
1501 lhs_.indicate_which(
1502 BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value
1509 // In the event of success, indicate new content type:
1510 lhs_.indicate_which(rhs_which_); // nothrow
1513 template <typename RhsT>
1515 const RhsT& rhs_content
1516 , mpl::false_// has_nothrow_copy
1517 , mpl::false_// has_nothrow_move_constructor
1518 , mpl::false_// has_fallback_type
1521 detail::variant::backup_assigner<wknd_self_t, RhsT>
1522 visitor(lhs_, rhs_which_, rhs_content);
1523 lhs_.internal_apply_visitor(visitor);
1526 public: // internal visitor interfaces
1528 template <typename RhsT>
1529 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
1530 internal_visit(const RhsT& rhs_content, int)
1532 typedef typename has_nothrow_copy<RhsT>::type
1534 typedef typename mpl::or_< // reduces compile-time
1536 , detail::variant::has_nothrow_move_constructor<RhsT>
1537 >::type nothrow_move_constructor;
1542 , nothrow_move_constructor()
1543 , has_fallback_type_()
1546 BOOST_VARIANT_AUX_RETURN_VOID;
1551 friend class assigner;
1553 void variant_assign(const variant& rhs)
1555 // If the contained types are EXACTLY the same...
1556 if (which_ == rhs.which_)
1558 // ...then assign rhs's storage to lhs's content:
1559 detail::variant::assign_storage visitor(rhs.storage_.address());
1560 this->internal_apply_visitor(visitor);
1564 // Otherwise, perform general (copy-based) variant assignment:
1565 assigner visitor(*this, rhs.which());
1566 rhs.internal_apply_visitor(visitor);
1570 private: // helpers, for modifiers (below)
1572 template <typename T>
1573 void assign(const T& rhs)
1575 // If direct T-to-T assignment is not possible...
1576 detail::variant::direct_assigner<const T> direct_assign(rhs);
1577 if (this->apply_visitor(direct_assign) == false)
1579 // ...then convert rhs to variant and assign:
1581 // While potentially inefficient, the following construction of a
1582 // variant allows T as any type convertible to one of the bounded
1583 // types without excessive code redundancy.
1586 variant_assign( detail::variant::move(temp) );
1590 public: // modifiers
1592 template <typename T>
1593 variant& operator=(const T& rhs)
1599 // [MSVC6 requires copy assign appear after templated operator=]
1600 variant& operator=(const variant& rhs)
1602 variant_assign(rhs);
1606 void swap(variant& rhs)
1608 // If the contained types are the same...
1609 if (which() == rhs.which())
1611 // ...then swap the values directly:
1612 detail::variant::swap_with<variant> visitor(rhs);
1613 this->apply_visitor(visitor);
1617 // ...otherwise, perform general variant swap:
1618 variant tmp( detail::variant::move(rhs) );
1619 rhs = detail::variant::move(*this);
1620 *this = detail::variant::move(tmp);
1627 // NOTE: member which() defined above.
1635 const std::type_info& type() const
1637 detail::variant::reflect visitor;
1638 return this->apply_visitor(visitor);
1641 public: // prevent comparison with foreign types
1643 #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
1645 # define BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE \
1651 // MSVC7 gives error about return types for above being different than
1652 // the true comparison operator overloads:
1655 # define BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE \
1658 #endif // MSVC7 workaround
1660 template <typename U>
1661 BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE
1662 operator==(const U&) const
1664 BOOST_STATIC_ASSERT( false && sizeof(U) );
1667 template <typename U>
1668 BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE
1669 operator<(const U&) const
1671 BOOST_STATIC_ASSERT( false && sizeof(U) );
1674 public: // comparison operators
1676 // [MSVC6 requires these operators appear after template operators]
1678 bool operator==(const variant& rhs) const
1680 if (this->which() != rhs.which())
1683 detail::variant::comparer<
1684 variant, detail::variant::equal_comp
1686 return rhs.apply_visitor(visitor);
1689 bool operator<(const variant& rhs) const
1692 // Dirk Schreib suggested this collating order.
1695 if (this->which() != rhs.which())
1696 return this->which() < rhs.which();
1698 detail::variant::comparer<
1699 variant, detail::variant::less_comp
1701 return rhs.apply_visitor(visitor);
1704 // helpers, for visitation support (below) -- private when possible
1705 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1707 template < BOOST_VARIANT_ENUM_PARAMS(typename U) >
1708 friend class variant;
1712 #else// defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1716 #endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1718 template <typename Visitor, typename VoidPtrCV>
1720 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1721 typename Visitor::result_type
1723 internal_apply_visitor_impl(
1730 typedef mpl::int_<0> first_which;
1731 typedef typename mpl::begin<internal_types>::type first_it;
1732 typedef typename mpl::end<internal_types>::type last_it;
1734 typedef detail::variant::visitation_impl_step<
1738 return detail::variant::visitation_impl(
1739 internal_which, logical_which
1740 , visitor, storage, mpl::false_()
1741 , never_uses_backup_flag()
1742 , static_cast<first_which*>(0), static_cast<first_step*>(0)
1746 template <typename Visitor>
1747 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1748 typename Visitor::result_type
1750 internal_apply_visitor(Visitor& visitor)
1752 return internal_apply_visitor_impl(
1753 which_, which(), visitor, storage_.address()
1757 template <typename Visitor>
1758 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1759 typename Visitor::result_type
1761 internal_apply_visitor(Visitor& visitor) const
1763 return internal_apply_visitor_impl(
1764 which_, which(), visitor, storage_.address()
1768 public: // visitation support
1770 template <typename Visitor>
1771 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1772 typename Visitor::result_type
1774 apply_visitor(Visitor& visitor)
1776 detail::variant::invoke_visitor<Visitor> invoker(visitor);
1777 return this->internal_apply_visitor(invoker);
1780 template <typename Visitor>
1781 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1782 typename Visitor::result_type
1784 apply_visitor(Visitor& visitor) const
1786 detail::variant::invoke_visitor<Visitor> invoker(visitor);
1787 return this->internal_apply_visitor(invoker);
1792 ///////////////////////////////////////////////////////////////////////////////
1793 // metafunction make_variant_over
1795 // See docs and boost/variant/variant_fwd.hpp for more information.
1797 template <typename Types>
1798 struct make_variant_over
1800 private: // precondition assertions
1802 #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
1803 BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value ));
1806 public: // metafunction result
1809 detail::variant::over_sequence< Types >
1814 ///////////////////////////////////////////////////////////////////////////////
1815 // function template swap
1817 // Swaps two variants of the same type (i.e., identical specification).
1819 template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
1821 variant< BOOST_VARIANT_ENUM_PARAMS(T) >& lhs
1822 , variant< BOOST_VARIANT_ENUM_PARAMS(T) >& rhs
1828 } // namespace boost
1830 // implementation additions
1831 #include "boost/variant/detail/variant_io.hpp"
1833 #endif // BOOST_VARIANT_VARIANT_HPP