fix doc example typo
[boost.git] / boost / variant / variant.hpp
blobecfde183d2ac20ea49af6211f79b7ba918a617e5
1 //-----------------------------------------------------------------------------
2 // boost variant/variant.hpp header file
3 // See http://www.boost.org for updates, documentation, and revision history.
4 //-----------------------------------------------------------------------------
5 //
6 // Copyright (c) 2002-2003
7 // Eric Friedman, Itay Maman
8 //
9 // Distributed under the Boost Software License, Version 1.0. (See
10 // accompanying file LICENSE_1_0.txt or copy at
11 // http://www.boost.org/LICENSE_1_0.txt)
13 #ifndef BOOST_VARIANT_VARIANT_HPP
14 #define BOOST_VARIANT_VARIANT_HPP
16 #include <cstddef> // for std::size_t
17 #include <new> // for placement new
18 #include <typeinfo> // for typeid, std::type_info
20 #include "boost/variant/detail/config.hpp"
21 #include "boost/mpl/aux_/config/eti.hpp"
22 #include "boost/mpl/aux_/value_wknd.hpp"
24 #include "boost/variant/variant_fwd.hpp"
25 #include "boost/variant/detail/backup_holder.hpp"
26 #include "boost/variant/detail/enable_recursive_fwd.hpp"
27 #include "boost/variant/detail/forced_return.hpp"
28 #include "boost/variant/detail/initializer.hpp"
29 #include "boost/variant/detail/make_variant_list.hpp"
30 #include "boost/variant/detail/over_sequence.hpp"
31 #include "boost/variant/detail/visitation_impl.hpp"
33 #include "boost/variant/detail/generic_result_type.hpp"
34 #include "boost/variant/detail/has_nothrow_move.hpp"
35 #include "boost/variant/detail/move.hpp"
37 #include "boost/detail/reference_content.hpp"
38 #include "boost/aligned_storage.hpp"
39 #include "boost/blank.hpp"
40 #include "boost/static_assert.hpp"
41 #include "boost/preprocessor/cat.hpp"
42 #include "boost/preprocessor/repeat.hpp"
43 #include "boost/type_traits/alignment_of.hpp"
44 #include "boost/type_traits/add_const.hpp"
45 #include "boost/type_traits/has_nothrow_constructor.hpp"
46 #include "boost/type_traits/has_nothrow_copy.hpp"
47 #include "boost/type_traits/is_const.hpp"
48 #include "boost/type_traits/is_same.hpp"
49 #include "boost/utility/enable_if.hpp"
50 #include "boost/variant/recursive_wrapper_fwd.hpp"
51 #include "boost/variant/static_visitor.hpp"
53 #include "boost/mpl/eval_if.hpp"
54 #include "boost/mpl/begin_end.hpp"
55 #include "boost/mpl/bool.hpp"
56 #include "boost/mpl/empty.hpp"
57 #include "boost/mpl/find_if.hpp"
58 #include "boost/mpl/front.hpp"
59 #include "boost/mpl/identity.hpp"
60 #include "boost/mpl/if.hpp"
61 #include "boost/mpl/int.hpp"
62 #include "boost/mpl/is_sequence.hpp"
63 #include "boost/mpl/iterator_range.hpp"
64 #include "boost/mpl/iter_fold_if.hpp"
65 #include "boost/mpl/logical.hpp"
66 #include "boost/mpl/max_element.hpp"
67 #include "boost/mpl/next.hpp"
68 #include "boost/mpl/deref.hpp"
69 #include "boost/mpl/pair.hpp"
70 #include "boost/mpl/protect.hpp"
71 #include "boost/mpl/push_front.hpp"
72 #include "boost/mpl/same_as.hpp"
73 #include "boost/mpl/size_t.hpp"
74 #include "boost/mpl/sizeof.hpp"
75 #include "boost/mpl/transform.hpp"
76 #include "boost/mpl/assert.hpp"
78 ///////////////////////////////////////////////////////////////////////////////
79 // Implementation Macros:
81 // BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
82 // Defined in boost/variant/detail/visitation_impl.hpp.
84 // BOOST_VARIANT_MINIMIZE_SIZE
85 // When #defined, implementation employs all known means to minimize the
86 // size of variant obje cts. However, often unsuccessful due to alignment
87 // issues, and potentially harmful to runtime speed, so not enabled by
88 // default. (TODO: Investigate further.)
90 #if defined(BOOST_VARIANT_MINIMIZE_SIZE)
91 # include <climits> // for SCHAR_MAX
92 # include "boost/mpl/eval_if.hpp"
93 # include "boost/mpl/equal_to.hpp"
94 # include "boost/mpl/identity.hpp"
95 # include "boost/mpl/int.hpp"
96 # include "boost/mpl/if.hpp"
97 # include "boost/mpl/less.hpp"
98 # include "boost/mpl/long.hpp"
99 # include "boost/mpl/O1_size.hpp"
100 #endif
103 namespace boost {
105 namespace detail { namespace variant {
107 ///////////////////////////////////////////////////////////////////////////////
108 // (detail) metafunction max_value
110 // Finds the maximum value of the unary metafunction F over Sequence.
112 template <typename Sequence, typename F>
113 struct max_value
115 private: // helpers, for metafunction result (below)
117 typedef typename mpl::transform1<Sequence, F>::type transformed_;
118 typedef typename mpl::max_element<transformed_
120 >::type max_it;
122 public: // metafunction result
124 typedef typename mpl::deref<max_it>::type
125 type;
129 ///////////////////////////////////////////////////////////////////////////////
130 // (detail) metafunction find_fallback_type
132 // Provides a fallback (i.e., nothrow default-constructible) type from the
133 // specified sequence, or no_fallback_type if not found.
135 // This implementation is designed to prefer boost::blank over other potential
136 // fallback types, regardless of its position in the specified sequence.
139 class no_fallback_type;
141 struct find_fallback_type_pred
143 template <typename Iterator>
144 struct apply
146 private:
147 typedef typename mpl::deref<Iterator>::type t_;
149 public:
150 typedef mpl::not_< has_nothrow_constructor<t_> > type;
154 template <typename Types>
155 struct find_fallback_type
157 private: // helpers, for metafunction result (below)
159 typedef typename mpl::end<Types>::type end_it;
161 // [Find the first suitable fallback type...]
163 typedef typename mpl::iter_fold_if<
164 Types
165 , mpl::int_<0>, mpl::protect< mpl::next<> >
166 , mpl::protect< find_fallback_type_pred >
167 >::type first_result_;
169 typedef typename first_result_::first first_result_index;
170 typedef typename first_result_::second first_result_it;
172 // [...now search the rest of the sequence for boost::blank...]
174 typedef typename mpl::iter_fold_if<
175 mpl::iterator_range< first_result_it,end_it >
176 , first_result_index, mpl::protect< mpl::next<> >
177 , mpl::protect< mpl::not_same_as<boost::blank> >
178 >::type second_result_;
180 typedef typename second_result_::second second_result_it;
182 public: // metafunction result
184 // [...and return the results of the search:]
185 typedef typename mpl::eval_if<
186 is_same< second_result_it,end_it >
187 , mpl::if_<
188 is_same< first_result_it,end_it >
189 , mpl::pair< no_fallback_type,no_fallback_type >
190 , first_result_
192 , mpl::identity< second_result_ >
193 >::type type;
197 #if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
199 template<>
200 struct find_fallback_type<int>
202 typedef mpl::pair< no_fallback_type,no_fallback_type > type;
205 #endif // BOOST_MPL_CFG_MSVC_60_ETI_BUG workaround
207 ///////////////////////////////////////////////////////////////////////////////
208 // (detail) metafunction make_storage
210 // Provides an aligned storage type capable of holding any of the types
211 // specified in the given type-sequence.
214 template <typename Types, typename NeverUsesBackupFlag>
215 struct make_storage
217 private: // helpers, for metafunction result (below)
219 typedef typename mpl::eval_if<
220 NeverUsesBackupFlag
221 , mpl::identity< Types >
222 , mpl::push_front<
223 Types, backup_holder<void*>
225 >::type types;
227 typedef typename max_value<
228 types, mpl::sizeof_<mpl::_1>
229 >::type max_size;
231 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
233 typedef typename max_value<
234 types, alignment_of<mpl::_1>
235 >::type max_alignment;
237 #else // borland
239 // temporary workaround -- use maximal alignment
240 typedef mpl::size_t< -1 > max_alignment;
242 #endif // borland workaround
244 public: // metafunction result
246 #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
248 typedef ::boost::aligned_storage<
249 BOOST_MPL_AUX_VALUE_WKND(max_size)::value
250 , BOOST_MPL_AUX_VALUE_WKND(max_alignment)::value
251 > type;
253 #else // MSVC7 and below
255 BOOST_STATIC_CONSTANT(std::size_t, msvc_max_size_c = max_size::value);
256 BOOST_STATIC_CONSTANT(std::size_t, msvc_max_alignment_c = max_alignment::value);
258 typedef ::boost::aligned_storage<
259 msvc_max_size_c
260 , msvc_max_alignment_c
261 > type;
263 #endif // MSVC workaround
267 #if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
269 template<>
270 struct make_storage<int,int>
272 typedef int type;
275 #endif // BOOST_MPL_CFG_MSVC_60_ETI_BUG workaround
277 ///////////////////////////////////////////////////////////////////////////////
278 // (detail) class destroyer
280 // Internal visitor that destroys the value it visits.
282 struct destroyer
283 : public static_visitor<>
285 public: // visitor interfaces
287 template <typename T>
288 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
289 internal_visit(T& operand, int) const
291 operand.~T();
293 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
294 operand; // suppresses warnings
295 #endif
297 BOOST_VARIANT_AUX_RETURN_VOID;
302 ///////////////////////////////////////////////////////////////////////////////
303 // (detail) class template known_get
305 // Visitor that returns a reference to content of the specified type.
307 // Precondition: visited variant MUST contain logical content of type T.
309 template <typename T>
310 class known_get
311 : public static_visitor<T&>
314 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
316 public: // visitor interface
318 T& operator()(T& operand) const
320 return operand;
323 template <typename U>
324 T& operator()(U&) const
326 // logical error to be here: see precondition above
327 BOOST_ASSERT(false);
328 return ::boost::detail::variant::forced_return< T& >();
331 #else // MSVC6
333 private: // helpers, for visitor interface (below)
335 T& execute(T& operand, mpl::true_) const
337 return operand;
340 template <typename U>
341 T& execute(U& operand, mpl::false_) const
343 // logical error to be here: see precondition above
344 BOOST_ASSERT(false);
345 return ::boost::detail::variant::forced_return< T& >();
348 public: // visitor interface
350 template <typename U>
351 T& operator()(U& operand) const
353 typedef typename is_same< U,T >::type
354 U_is_T;
356 return execute(operand, U_is_T());
359 #endif // MSVC6 workaround
363 ///////////////////////////////////////////////////////////////////////////////
364 // (detail) class copy_into
366 // Internal visitor that copies the value it visits into the given buffer.
368 class copy_into
369 : public static_visitor<>
371 private: // representation
373 void* storage_;
375 public: // structors
377 explicit copy_into(void* storage)
378 : storage_(storage)
382 public: // internal visitor interface
384 template <typename T>
385 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
386 internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
388 new(storage_) T( operand.get() );
389 BOOST_VARIANT_AUX_RETURN_VOID;
392 template <typename T>
393 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
394 internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
396 new(storage_) T( operand.get() );
397 BOOST_VARIANT_AUX_RETURN_VOID;
400 template <typename T>
401 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
402 internal_visit(const T& operand, int) const
404 new(storage_) T(operand);
405 BOOST_VARIANT_AUX_RETURN_VOID;
410 ///////////////////////////////////////////////////////////////////////////////
411 // (detail) class assign_storage
413 // Internal visitor that assigns the given storage (which must be a
414 // constructed value of the same type) to the value it visits.
416 struct assign_storage
417 : public static_visitor<>
419 private: // representation
421 const void* rhs_storage_;
423 public: // structors
425 explicit assign_storage(const void* rhs_storage)
426 : rhs_storage_(rhs_storage)
430 public: // internal visitor interfaces
432 template <typename T>
433 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
434 internal_visit(backup_holder<T>& lhs_content, long) const
436 lhs_content.get()
437 = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
438 BOOST_VARIANT_AUX_RETURN_VOID;
441 template <typename T>
442 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
443 internal_visit(const backup_holder<T>& lhs_content, long) const
445 lhs_content.get()
446 = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
447 BOOST_VARIANT_AUX_RETURN_VOID;
450 template <typename T>
451 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
452 internal_visit(T& lhs_content, int) const
454 // NOTE TO USER :
455 // Compile error here indicates one of variant's bounded types does
456 // not meet the requirements of the Assignable concept. Thus,
457 // variant is not Assignable.
459 // Hint: Are any of the bounded types const-qualified or references?
461 lhs_content = *static_cast< const T* >(rhs_storage_);
462 BOOST_VARIANT_AUX_RETURN_VOID;
467 ///////////////////////////////////////////////////////////////////////////////
468 // (detail) class direct_assigner
470 // Generic static visitor that: if and only if the visited value is of the
471 // specified type, assigns the given value to the visited value and returns
472 // true; else returns false.
474 template <typename T>
475 class direct_assigner
476 : public static_visitor<bool>
478 private: // representation
480 const T& rhs_;
482 public: // structors
484 explicit direct_assigner(const T& rhs)
485 : rhs_(rhs)
489 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
491 public: // visitor interface
493 bool operator()(T& lhs)
495 lhs = rhs_;
496 return true;
499 template <typename U>
500 bool operator()(U&)
502 return false;
505 #else // MSVC6
507 private: // helpers, for visitor interface (below)
509 bool execute(T& lhs, mpl::true_)
511 lhs = rhs_;
512 return true;
515 template <typename U>
516 bool execute(U&, mpl::false_)
518 return false;
521 public: // visitor interface
523 template <typename U>
524 bool operator()(U& lhs)
526 typedef typename is_same<U,T>::type U_is_T;
527 return execute(lhs, U_is_T());
530 #endif // MSVC6 workaround
534 ///////////////////////////////////////////////////////////////////////////////
535 // (detail) class backup_assigner
537 // Internal visitor that "assigns" the given value to the visited value,
538 // using backup to recover if the destroy-copy sequence fails.
540 // NOTE: This needs to be a friend of variant, as it needs access to
541 // indicate_which, indicate_backup_which, etc.
543 template <typename Variant, typename RhsT>
544 class backup_assigner
545 : public static_visitor<>
547 private: // representation
549 Variant& lhs_;
550 int rhs_which_;
551 const RhsT& rhs_content_;
553 public: // structors
555 backup_assigner(Variant& lhs, int rhs_which, const RhsT& rhs_content)
556 : lhs_(lhs)
557 , rhs_which_(rhs_which)
558 , rhs_content_(rhs_content)
562 private: // helpers, for visitor interface (below)
564 template <typename LhsT>
565 void backup_assign_impl(
566 LhsT& lhs_content
567 , mpl::true_// has_nothrow_move
570 // Move lhs content to backup...
571 LhsT backup_lhs_content(
572 ::boost::detail::variant::move(lhs_content)
573 ); // nothrow
575 // ...destroy lhs content...
576 lhs_content.~LhsT(); // nothrow
580 // ...and attempt to copy rhs content into lhs storage:
581 new(lhs_.storage_.address()) RhsT(rhs_content_);
583 catch (...)
585 // In case of failure, restore backup content to lhs storage...
586 new(lhs_.storage_.address())
587 LhsT(
588 ::boost::detail::variant::move(backup_lhs_content)
589 ); // nothrow
591 // ...and rethrow:
592 throw;
595 // In case of success, indicate new content type:
596 lhs_.indicate_which(rhs_which_); // nothrow
599 template <typename LhsT>
600 void backup_assign_impl(
601 LhsT& lhs_content
602 , mpl::false_// has_nothrow_move
605 // Backup lhs content...
606 LhsT* backup_lhs_ptr = new LhsT(lhs_content);
608 // ...destroy lhs content...
609 lhs_content.~LhsT(); // nothrow
613 // ...and attempt to copy rhs content into lhs storage:
614 new(lhs_.storage_.address()) RhsT(rhs_content_);
616 catch (...)
618 // In case of failure, copy backup pointer to lhs storage...
619 new(lhs_.storage_.address())
620 backup_holder<LhsT>( backup_lhs_ptr ); // nothrow
622 // ...indicate now using backup...
623 lhs_.indicate_backup_which( lhs_.which() ); // nothrow
625 // ...and rethrow:
626 throw;
629 // In case of success, indicate new content type...
630 lhs_.indicate_which(rhs_which_); // nothrow
632 // ...and delete backup:
633 delete backup_lhs_ptr; // nothrow
636 public: // visitor interface
638 template <typename LhsT>
639 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
640 internal_visit(LhsT& lhs_content, int)
642 typedef typename has_nothrow_move_constructor<LhsT>::type
643 nothrow_move;
645 backup_assign_impl( lhs_content, nothrow_move() );
647 BOOST_VARIANT_AUX_RETURN_VOID;
652 ///////////////////////////////////////////////////////////////////////////////
653 // (detail) class swap_with
655 // Visitor that swaps visited value with content of given variant.
657 // Precondition: Given variant MUST have same logical type as visited value.
659 template <typename Variant>
660 struct swap_with
661 : public static_visitor<>
663 private: // representation
665 Variant& toswap_;
667 public: // structors
669 explicit swap_with(Variant& toswap)
670 : toswap_(toswap)
674 public: // internal visitor interfaces
676 template <typename T>
677 void operator()(T& operand) const
679 // Since the precondition ensures types are same, get T...
680 known_get<T> getter;
681 T& other = toswap_.apply_visitor(getter);
683 // ...and swap:
684 ::boost::detail::variant::move_swap( operand, other );
689 ///////////////////////////////////////////////////////////////////////////////
690 // (detail) class reflect
692 // Generic static visitor that performs a typeid on the value it visits.
694 class reflect
695 : public static_visitor<const std::type_info&>
697 public: // visitor interfaces
699 template <typename T>
700 const std::type_info& operator()(const T&) const
702 return typeid(T);
707 ///////////////////////////////////////////////////////////////////////////////
708 // (detail) class comparer
710 // Generic static visitor that compares the content of the given lhs variant
711 // with the visited rhs content using Comp.
713 // Precondition: lhs.which() == rhs.which()
715 template <typename Variant, typename Comp>
716 class comparer
717 : public static_visitor<bool>
719 private: // representation
721 const Variant& lhs_;
723 public: // structors
725 explicit comparer(const Variant& lhs)
726 : lhs_(lhs)
730 public: // visitor interfaces
732 template <typename T>
733 bool operator()(const T& rhs_content) const
735 // Since the precondition ensures lhs and rhs types are same, get T...
736 known_get<const T> getter;
737 const T& lhs_content = lhs_.apply_visitor(getter);
739 // ...and compare lhs and rhs contents:
740 return Comp()(lhs_content, rhs_content);
745 ///////////////////////////////////////////////////////////////////////////////
746 // (detail) class equal_comp
748 // Generic function object compares lhs with rhs using operator==.
750 struct equal_comp
752 template <typename T>
753 bool operator()(const T& lhs, const T& rhs) const
755 return lhs == rhs;
759 ///////////////////////////////////////////////////////////////////////////////
760 // (detail) class less_comp
762 // Generic function object compares lhs with rhs using operator<.
764 struct less_comp
766 template <typename T>
767 bool operator()(const T& lhs, const T& rhs) const
769 return lhs < rhs;
773 ///////////////////////////////////////////////////////////////////////////////
774 // (detail) class template invoke_visitor
776 // Internal visitor that invokes the given visitor using:
777 // * for wrappers (e.g., recursive_wrapper), the wrapper's held value.
778 // * for all other values, the value itself.
780 template <typename Visitor>
781 class invoke_visitor
783 private: // representation
785 Visitor& visitor_;
787 public: // visitor typedefs
789 typedef typename Visitor::result_type
790 result_type;
792 public: // structors
794 explicit invoke_visitor(Visitor& visitor)
795 : visitor_(visitor)
799 #if !defined(BOOST_NO_VOID_RETURNS)
801 public: // internal visitor interfaces
803 template <typename T>
804 result_type internal_visit(T& operand, int)
806 return visitor_(operand);
809 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
810 template <typename T>
811 result_type internal_visit(const T& operand, int)
813 return visitor_(operand);
815 # endif
817 #else // defined(BOOST_NO_VOID_RETURNS)
819 private: // helpers, for internal visitor interfaces (below)
821 template <typename T>
822 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
823 visit_impl(T& operand, mpl::false_)
825 return visitor_(operand);
828 template <typename T>
829 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
830 visit_impl(T& operand, mpl::true_)
832 visitor_(operand);
833 BOOST_VARIANT_AUX_RETURN_VOID;
836 public: // internal visitor interfaces
838 template <typename T>
839 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
840 internal_visit(T& operand, int)
842 typedef typename is_same<result_type, void>::type
843 has_void_result_type;
845 return visit_impl(operand, has_void_result_type());
848 #endif // BOOST_NO_VOID_RETURNS) workaround
850 public: // internal visitor interfaces, cont.
852 template <typename T>
853 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
854 internal_visit(boost::recursive_wrapper<T>& operand, long)
856 return internal_visit( operand.get(), 1L );
859 template <typename T>
860 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
861 internal_visit(const boost::recursive_wrapper<T>& operand, long)
863 return internal_visit( operand.get(), 1L );
866 template <typename T>
867 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
868 internal_visit(boost::detail::reference_content<T>& operand, long)
870 return internal_visit( operand.get(), 1L );
873 template <typename T>
874 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
875 internal_visit(const boost::detail::reference_content<T>& operand, long)
877 return internal_visit( operand.get(), 1L );
880 template <typename T>
881 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
882 internal_visit(boost::detail::variant::backup_holder<T>& operand, long)
884 return internal_visit( operand.get(), 1L );
887 template <typename T>
888 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
889 internal_visit(const boost::detail::variant::backup_holder<T>& operand, long)
891 return internal_visit( operand.get(), 1L );
896 }} // namespace detail::variant
898 ///////////////////////////////////////////////////////////////////////////////
899 // class template variant (concept inspired by Andrei Alexandrescu)
901 // See docs and boost/variant/variant_fwd.hpp for more information.
903 template <
904 typename T0_
905 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)
907 class variant
909 private: // helpers, for typedefs (below)
911 typedef variant wknd_self_t;
913 struct is_recursive_
914 : detail::variant::is_recursive_flag<T0_>
918 typedef typename mpl::eval_if<
919 is_recursive_
920 , T0_
921 , mpl::identity< T0_ >
922 >::type unwrapped_T0_;
924 struct is_sequence_based_
925 : detail::variant::is_over_sequence<unwrapped_T0_>
929 #if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
931 private: // helpers, for typedefs (below)
933 typedef typename mpl::eval_if<
934 is_sequence_based_
935 , unwrapped_T0_ // over_sequence<...>::type
936 , detail::variant::make_variant_list<
937 unwrapped_T0_
938 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
940 >::type specified_types;
942 BOOST_STATIC_ASSERT((
943 ::boost::mpl::not_< mpl::empty<specified_types> >::value
946 typedef typename mpl::eval_if<
947 is_recursive_
948 , mpl::transform<
949 specified_types
950 , mpl::protect<
951 detail::variant::quoted_enable_recursive<wknd_self_t>
954 , mpl::identity< specified_types >
955 >::type recursive_enabled_types;
957 public: // public typedefs
959 typedef typename mpl::transform<
960 recursive_enabled_types
961 , unwrap_recursive<mpl::_1>
962 >::type types;
964 private: // internal typedefs
966 typedef typename mpl::transform<
967 recursive_enabled_types
968 , mpl::protect< detail::make_reference_content<> >
969 >::type internal_types;
971 typedef typename mpl::front<
972 internal_types
973 >::type internal_T0;
975 #else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
977 private: // helpers, for typedefs (below)
979 typedef unwrapped_T0_ T0;
981 #define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
982 typedef typename mpl::eval_if< \
983 is_recursive_ \
984 , detail::variant::enable_recursive< \
985 BOOST_PP_CAT(T,N) \
986 , wknd_self_t \
988 , mpl::identity< BOOST_PP_CAT(T,N) > \
989 >::type BOOST_PP_CAT(recursive_enabled_T,N); \
990 /**/
992 BOOST_PP_REPEAT(
993 BOOST_VARIANT_LIMIT_TYPES
994 , BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
998 #undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1000 #define BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS(z,N,_) \
1001 typedef typename unwrap_recursive< \
1002 BOOST_PP_CAT(recursive_enabled_T,N) \
1003 >::type BOOST_PP_CAT(public_T,N); \
1004 /**/
1006 BOOST_PP_REPEAT(
1007 BOOST_VARIANT_LIMIT_TYPES
1008 , BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1012 #undef BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1014 public: // public typedefs
1016 typedef typename detail::variant::make_variant_list<
1017 BOOST_VARIANT_ENUM_PARAMS(public_T)
1018 >::type types;
1020 private: // helpers, for internal typedefs (below)
1022 #define BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS(z,N,_) \
1023 typedef detail::make_reference_content< \
1024 BOOST_PP_CAT(recursive_enabled_T,N) \
1025 >::type BOOST_PP_CAT(internal_T,N); \
1026 /**/
1028 BOOST_PP_REPEAT(
1029 BOOST_VARIANT_LIMIT_TYPES
1030 , BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1034 #undef BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1036 private: // internal typedefs
1038 typedef typename detail::variant::make_variant_list<
1039 BOOST_VARIANT_ENUM_PARAMS(internal_T)
1040 >::type internal_types;
1042 private: // static precondition assertions
1044 // NOTE TO USER :
1045 // variant< type-sequence > syntax is not supported on this compiler!
1047 BOOST_MPL_ASSERT_NOT(( is_sequence_based_ ));
1049 #endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT workaround
1051 private: // helpers, for representation (below)
1053 typedef typename detail::variant::find_fallback_type<
1054 internal_types
1055 >::type fallback_type_result_;
1057 typedef typename fallback_type_result_::first
1058 fallback_type_index_;
1059 typedef typename fallback_type_result_::second
1060 fallback_type_;
1062 struct has_fallback_type_
1063 : mpl::not_<
1064 is_same< fallback_type_, detail::variant::no_fallback_type >
1069 typedef has_fallback_type_
1070 never_uses_backup_flag;
1072 typedef typename detail::variant::make_storage<
1073 internal_types, never_uses_backup_flag
1074 >::type storage_t;
1076 private: // helpers, for representation (below)
1078 // which_ on:
1079 // * [0, size<internal_types>) indicates stack content
1080 // * [-size<internal_types>, 0) indicates pointer to heap backup
1081 // if which_ >= 0:
1082 // * then which() -> which_
1083 // * else which() -> -(which_ + 1)
1085 #if !defined(BOOST_VARIANT_MINIMIZE_SIZE)
1087 typedef int which_t;
1089 #else // defined(BOOST_VARIANT_MINIMIZE_SIZE)
1091 // [if O1_size available, then attempt which_t size optimization...]
1092 // [select signed char if fewer than SCHAR_MAX types, else signed int:]
1093 typedef typename mpl::eval_if<
1094 mpl::equal_to< mpl::O1_size<internal_types>, mpl::long_<-1> >
1095 , mpl::identity< int >
1096 , mpl::if_<
1097 mpl::less< mpl::O1_size<internal_types>, mpl::int_<SCHAR_MAX> >
1098 , signed char
1099 , int
1101 >::type which_t;
1103 #endif // BOOST_VARIANT_MINIMIZE_SIZE switch
1105 // representation -- private when possible
1106 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1107 private:
1108 #else
1109 public:
1110 #endif
1112 which_t which_;
1113 storage_t storage_;
1115 void indicate_which(int which)
1117 which_ = static_cast<which_t>( which );
1120 void indicate_backup_which(int which)
1122 which_ = static_cast<which_t>( -(which + 1) );
1125 private: // helpers, for queries (below)
1127 bool using_backup() const
1129 return which_ < 0;
1132 public: // queries
1134 int which() const
1136 // If using heap backup...
1137 if (using_backup())
1138 // ...then return adjusted which_:
1139 return -(which_ + 1);
1141 // Otherwise, return which_ directly:
1142 return which_;
1145 private: // helpers, for structors (below)
1147 struct initializer
1148 : BOOST_VARIANT_AUX_INITIALIZER_T(
1149 recursive_enabled_types, recursive_enabled_T
1154 void destroy_content()
1156 detail::variant::destroyer visitor;
1157 this->internal_apply_visitor(visitor);
1160 public: // structors
1162 ~variant()
1164 destroy_content();
1167 variant()
1169 // NOTE TO USER :
1170 // Compile error from here indicates that the first bound
1171 // type is not default-constructible, and so variant cannot
1172 // support its own default-construction.
1174 new( storage_.address() ) internal_T0();
1175 indicate_which(0); // zero is the index of the first bounded type
1178 private: // helpers, for structors, cont. (below)
1180 class convert_copy_into
1181 : public static_visitor<int>
1183 private: // representation
1185 void* storage_;
1187 public: // structors
1189 explicit convert_copy_into(void* storage)
1190 : storage_(storage)
1194 public: // internal visitor interfaces (below)
1196 template <typename T>
1197 int internal_visit(T& operand, int) const
1199 // NOTE TO USER :
1200 // Compile error here indicates one of the source variant's types
1201 // cannot be unambiguously converted to the destination variant's
1202 // types (or that no conversion exists).
1204 return initializer::initialize(storage_, operand);
1207 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
1208 template <typename T>
1209 result_type internal_visit(const T& operand, int) const
1211 return initializer::initialize(storage_, operand);
1213 # endif
1215 template <typename T>
1216 int internal_visit(boost::detail::reference_content<T>& operand, long) const
1218 return internal_visit( operand.get(), 1L );
1221 template <typename T>
1222 int internal_visit(const boost::detail::reference_content<T>& operand, long) const
1224 return internal_visit( operand.get(), 1L );
1227 template <typename T>
1228 int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
1230 return internal_visit( operand.get(), 1L );
1233 template <typename T>
1234 int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
1236 return internal_visit( operand.get(), 1L );
1239 template <typename T>
1240 int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1242 return internal_visit( operand.get(), 1L );
1245 template <typename T>
1246 int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
1248 return internal_visit( operand.get(), 1L );
1253 friend class convert_copy_into;
1255 private: // helpers, for structors, below
1257 template <typename T>
1258 void convert_construct(
1259 T& operand
1260 , int
1261 , mpl::false_ = mpl::false_() // is_foreign_variant
1264 // NOTE TO USER :
1265 // Compile error here indicates that the given type is not
1266 // unambiguously convertible to one of the variant's types
1267 // (or that no conversion exists).
1269 indicate_which(
1270 initializer::initialize(
1271 storage_.address()
1272 , operand
1277 template <typename Variant>
1278 void convert_construct(
1279 Variant& operand
1280 , long
1281 , mpl::true_// is_foreign_variant
1284 convert_copy_into visitor(storage_.address());
1285 indicate_which(
1286 operand.internal_apply_visitor(visitor)
1290 template <typename Variant>
1291 void convert_construct_variant(Variant& operand)
1293 // [Determine if the given variant is itself a bounded type, or if its
1294 // content needs to be converted (i.e., it is a 'foreign' variant):]
1297 typedef typename mpl::find_if<
1298 types
1299 , is_same<
1300 add_const<mpl::_1>
1301 , const Variant
1303 >::type found_it;
1305 typedef typename mpl::end<types>::type not_found;
1306 typedef typename is_same<
1307 found_it, not_found
1308 >::type is_foreign_variant;
1310 // Convert construct from operand:
1311 convert_construct(
1312 operand, 1L
1313 , is_foreign_variant()
1317 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1318 void convert_construct(
1319 boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1320 , long
1323 convert_construct_variant(operand);
1326 template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1327 void convert_construct(
1328 const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1329 , long
1332 convert_construct_variant(operand);
1335 public: // structors, cont.
1337 #if !defined(BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING)
1339 template <typename T>
1340 variant(const T& operand)
1342 convert_construct(operand, 1L);
1345 template <typename T>
1346 variant(T& operand)
1348 convert_construct(operand, 1L);
1351 #elif defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND)
1353 // For compilers that cannot distinguish between T& and const T& in
1354 // template constructors, but do fully support SFINAE, we can workaround:
1356 template <typename T>
1357 variant(const T& operand)
1359 convert_construct(operand, 1L);
1362 template <typename T>
1363 variant(
1364 T& operand
1365 , typename enable_if<
1366 mpl::not_< is_const<T> >
1367 , void
1368 >::type* = 0
1371 convert_construct(operand, 1L);
1374 #else // !defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND)
1376 // For compilers that cannot distinguish between T& and const T& in
1377 // template constructors, and do NOT support SFINAE, we can't workaround:
1379 template <typename T>
1380 variant(const T& operand)
1382 convert_construct(operand, 1L);
1385 #endif // BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING workarounds
1387 public: // structors, cont.
1389 // [MSVC6 requires copy constructor appear after template constructors]
1390 variant(const variant& operand)
1392 // Copy the value of operand into *this...
1393 detail::variant::copy_into visitor( storage_.address() );
1394 operand.internal_apply_visitor(visitor);
1396 // ...and activate the *this's primary storage on success:
1397 indicate_which(operand.which());
1400 private: // helpers, for modifiers (below)
1402 # if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1403 template <typename Variant, typename RhsT>
1404 friend class detail::variant::backup_assigner;
1405 # endif
1407 // class assigner
1409 // Internal visitor that "assigns" the visited value to the given variant
1410 // by appropriate destruction and copy-construction.
1413 class assigner
1414 : public static_visitor<>
1416 private: // representation
1418 variant& lhs_;
1419 int rhs_which_;
1421 public: // structors
1423 assigner(variant& lhs, int rhs_which)
1424 : lhs_(lhs)
1425 , rhs_which_(rhs_which)
1429 private: // helpers, for internal visitor interface (below)
1431 template <typename RhsT, typename B1, typename B2>
1432 void assign_impl(
1433 const RhsT& rhs_content
1434 , mpl::true_// has_nothrow_copy
1435 , B1// has_nothrow_move_constructor
1436 , B2// has_fallback_type
1439 // Destroy lhs's content...
1440 lhs_.destroy_content(); // nothrow
1442 // ...copy rhs content into lhs's storage...
1443 new(lhs_.storage_.address())
1444 RhsT( rhs_content ); // nothrow
1446 // ...and indicate new content type:
1447 lhs_.indicate_which(rhs_which_); // nothrow
1450 template <typename RhsT, typename B>
1451 void assign_impl(
1452 const RhsT& rhs_content
1453 , mpl::false_// has_nothrow_copy
1454 , mpl::true_// has_nothrow_move_constructor
1455 , B// has_fallback_type
1458 // Attempt to make a temporary copy (so as to move it below)...
1459 RhsT temp(rhs_content);
1461 // ...and upon success destroy lhs's content...
1462 lhs_.destroy_content(); // nothrow
1464 // ...move the temporary copy into lhs's storage...
1465 new(lhs_.storage_.address())
1466 RhsT( detail::variant::move(temp) ); // nothrow
1468 // ...and indicate new content type:
1469 lhs_.indicate_which(rhs_which_); // nothrow
1472 template <typename RhsT>
1473 void assign_impl(
1474 const RhsT& rhs_content
1475 , mpl::false_// has_nothrow_copy
1476 , mpl::false_// has_nothrow_move_constructor
1477 , mpl::true_// has_fallback_type
1480 // Destroy lhs's content...
1481 lhs_.destroy_content(); // nothrow
1485 // ...and attempt to copy rhs's content into lhs's storage:
1486 new(lhs_.storage_.address())
1487 RhsT( rhs_content );
1489 catch (...)
1491 // In case of failure, default-construct fallback type in lhs's storage...
1492 new (lhs_.storage_.address())
1493 fallback_type_; // nothrow
1495 // ...indicate construction of fallback type...
1496 lhs_.indicate_which(
1497 BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value
1498 ); // nothrow
1500 // ...and rethrow:
1501 throw;
1504 // In the event of success, indicate new content type:
1505 lhs_.indicate_which(rhs_which_); // nothrow
1508 template <typename RhsT>
1509 void assign_impl(
1510 const RhsT& rhs_content
1511 , mpl::false_// has_nothrow_copy
1512 , mpl::false_// has_nothrow_move_constructor
1513 , mpl::false_// has_fallback_type
1516 detail::variant::backup_assigner<wknd_self_t, RhsT>
1517 visitor(lhs_, rhs_which_, rhs_content);
1518 lhs_.internal_apply_visitor(visitor);
1521 public: // internal visitor interfaces
1523 template <typename RhsT>
1524 BOOST_VARIANT_AUX_RETURN_VOID_TYPE
1525 internal_visit(const RhsT& rhs_content, int)
1527 typedef typename has_nothrow_copy<RhsT>::type
1528 nothrow_copy;
1529 typedef typename mpl::or_< // reduces compile-time
1530 nothrow_copy
1531 , detail::variant::has_nothrow_move_constructor<RhsT>
1532 >::type nothrow_move_constructor;
1534 assign_impl(
1535 rhs_content
1536 , nothrow_copy()
1537 , nothrow_move_constructor()
1538 , has_fallback_type_()
1541 BOOST_VARIANT_AUX_RETURN_VOID;
1546 friend class assigner;
1548 void variant_assign(const variant& rhs)
1550 // If the contained types are EXACTLY the same...
1551 if (which_ == rhs.which_)
1553 // ...then assign rhs's storage to lhs's content:
1554 detail::variant::assign_storage visitor(rhs.storage_.address());
1555 this->internal_apply_visitor(visitor);
1557 else
1559 // Otherwise, perform general (copy-based) variant assignment:
1560 assigner visitor(*this, rhs.which());
1561 rhs.internal_apply_visitor(visitor);
1565 private: // helpers, for modifiers (below)
1567 template <typename T>
1568 void assign(const T& rhs)
1570 // If direct T-to-T assignment is not possible...
1571 detail::variant::direct_assigner<T> direct_assign(rhs);
1572 if (this->apply_visitor(direct_assign) == false)
1574 // ...then convert rhs to variant and assign:
1576 // While potentially inefficient, the following construction of a
1577 // variant allows T as any type convertible to one of the bounded
1578 // types without excessive code redundancy.
1580 variant temp(rhs);
1581 variant_assign( detail::variant::move(temp) );
1585 public: // modifiers
1587 template <typename T>
1588 variant& operator=(const T& rhs)
1590 assign(rhs);
1591 return *this;
1594 // [MSVC6 requires copy assign appear after templated operator=]
1595 variant& operator=(const variant& rhs)
1597 variant_assign(rhs);
1598 return *this;
1601 void swap(variant& rhs)
1603 // If the contained types are the same...
1604 if (which() == rhs.which())
1606 // ...then swap the values directly:
1607 detail::variant::swap_with<variant> visitor(rhs);
1608 this->apply_visitor(visitor);
1610 else
1612 // ...otherwise, perform general variant swap:
1613 variant tmp( detail::variant::move(rhs) );
1614 rhs = detail::variant::move(*this);
1615 *this = detail::variant::move(tmp);
1619 public: // queries
1622 // NOTE: member which() defined above.
1625 bool empty() const
1627 return false;
1630 const std::type_info& type() const
1632 detail::variant::reflect visitor;
1633 return this->apply_visitor(visitor);
1636 public: // prevent comparison with foreign types
1638 #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
1640 # define BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE \
1641 void
1643 #else // MSVC7
1646 // MSVC7 gives error about return types for above being different than
1647 // the true comparison operator overloads:
1650 # define BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE \
1651 bool
1653 #endif // MSVC7 workaround
1655 template <typename U>
1656 BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE
1657 operator==(const U&) const
1659 BOOST_STATIC_ASSERT( false && sizeof(U) );
1662 template <typename U>
1663 BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE
1664 operator<(const U&) const
1666 BOOST_STATIC_ASSERT( false && sizeof(U) );
1669 public: // comparison operators
1671 // [MSVC6 requires these operators appear after template operators]
1673 bool operator==(const variant& rhs) const
1675 if (this->which() != rhs.which())
1676 return false;
1678 detail::variant::comparer<
1679 variant, detail::variant::equal_comp
1680 > visitor(*this);
1681 return rhs.apply_visitor(visitor);
1684 bool operator<(const variant& rhs) const
1687 // Dirk Schreib suggested this collating order.
1690 if (this->which() != rhs.which())
1691 return this->which() < rhs.which();
1693 detail::variant::comparer<
1694 variant, detail::variant::less_comp
1695 > visitor(*this);
1696 return rhs.apply_visitor(visitor);
1699 // helpers, for visitation support (below) -- private when possible
1700 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1702 template < BOOST_VARIANT_ENUM_PARAMS(typename U) >
1703 friend class variant;
1705 private:
1707 #else// defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1709 public:
1711 #endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1713 template <typename Visitor, typename VoidPtrCV>
1714 static
1715 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1716 typename Visitor::result_type
1718 internal_apply_visitor_impl(
1719 int internal_which
1720 , int logical_which
1721 , Visitor& visitor
1722 , VoidPtrCV storage
1725 typedef mpl::int_<0> first_which;
1726 typedef typename mpl::begin<internal_types>::type first_it;
1727 typedef typename mpl::end<internal_types>::type last_it;
1729 typedef detail::variant::visitation_impl_step<
1730 first_it, last_it
1731 > first_step;
1733 return detail::variant::visitation_impl(
1734 internal_which, logical_which
1735 , visitor, storage, mpl::false_()
1736 , never_uses_backup_flag()
1737 , static_cast<first_which*>(0), static_cast<first_step*>(0)
1741 template <typename Visitor>
1742 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1743 typename Visitor::result_type
1745 internal_apply_visitor(Visitor& visitor)
1747 return internal_apply_visitor_impl(
1748 which_, which(), visitor, storage_.address()
1752 template <typename Visitor>
1753 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1754 typename Visitor::result_type
1756 internal_apply_visitor(Visitor& visitor) const
1758 return internal_apply_visitor_impl(
1759 which_, which(), visitor, storage_.address()
1763 public: // visitation support
1765 template <typename Visitor>
1766 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1767 typename Visitor::result_type
1769 apply_visitor(Visitor& visitor)
1771 detail::variant::invoke_visitor<Visitor> invoker(visitor);
1772 return this->internal_apply_visitor(invoker);
1775 template <typename Visitor>
1776 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
1777 typename Visitor::result_type
1779 apply_visitor(Visitor& visitor) const
1781 detail::variant::invoke_visitor<Visitor> invoker(visitor);
1782 return this->internal_apply_visitor(invoker);
1785 }; // class variant
1787 ///////////////////////////////////////////////////////////////////////////////
1788 // metafunction make_variant_over
1790 // See docs and boost/variant/variant_fwd.hpp for more information.
1792 template <typename Types>
1793 struct make_variant_over
1795 private: // precondition assertions
1797 #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
1798 BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value ));
1799 #endif
1801 public: // metafunction result
1803 typedef variant<
1804 detail::variant::over_sequence< Types >
1805 > type;
1809 ///////////////////////////////////////////////////////////////////////////////
1810 // function template swap
1812 // Swaps two variants of the same type (i.e., identical specification).
1814 template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
1815 inline void swap(
1816 variant< BOOST_VARIANT_ENUM_PARAMS(T) >& lhs
1817 , variant< BOOST_VARIANT_ENUM_PARAMS(T) >& rhs
1820 lhs.swap(rhs);
1823 } // namespace boost
1825 // implementation additions
1826 #include "boost/variant/detail/variant_io.hpp"
1828 #endif // BOOST_VARIANT_VARIANT_HPP