Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:33

0001 //-----------------------------------------------------------------------------
0002 // boost variant/variant.hpp header file
0003 // See http://www.boost.org for updates, documentation, and revision history.
0004 //-----------------------------------------------------------------------------
0005 //
0006 // Copyright (c) 2002-2003 Eric Friedman, Itay Maman
0007 // Copyright (c) 2012-2023 Antony Polukhin
0008 //
0009 // Distributed under the Boost Software License, Version 1.0. (See
0010 // accompanying file LICENSE_1_0.txt or copy at
0011 // http://www.boost.org/LICENSE_1_0.txt)
0012 
0013 // Thanks to Adam Romanek for providing patches for exception-disabled env.
0014 
0015 #ifndef BOOST_VARIANT_VARIANT_HPP
0016 #define BOOST_VARIANT_VARIANT_HPP
0017 
0018 #include <cstddef> // for std::size_t
0019 #include <new> // for placement new
0020 
0021 #include <boost/type_index.hpp>
0022 
0023 #include <boost/variant/detail/config.hpp>
0024 #include <boost/mpl/aux_/value_wknd.hpp>
0025 
0026 #include <boost/variant/variant_fwd.hpp>
0027 #include <boost/variant/detail/backup_holder.hpp>
0028 #include <boost/variant/detail/enable_recursive_fwd.hpp>
0029 #include <boost/variant/detail/forced_return.hpp>
0030 #include <boost/variant/detail/initializer.hpp>
0031 #include <boost/variant/detail/make_variant_list.hpp>
0032 #include <boost/variant/detail/over_sequence.hpp>
0033 #include <boost/variant/detail/visitation_impl.hpp>
0034 #include <boost/variant/detail/hash_variant.hpp>
0035 #include <boost/variant/detail/std_hash.hpp>
0036 
0037 #include <boost/variant/detail/move.hpp>
0038 
0039 #include <boost/detail/reference_content.hpp>
0040 #include <boost/blank.hpp>
0041 #include <boost/integer/common_factor_ct.hpp>
0042 #include <boost/static_assert.hpp>
0043 #include <boost/preprocessor/cat.hpp>
0044 #include <boost/preprocessor/repeat.hpp>
0045 #include <boost/type_traits/aligned_storage.hpp>
0046 #include <boost/type_traits/alignment_of.hpp>
0047 #include <boost/type_traits/add_const.hpp>
0048 #include <boost/type_traits/has_nothrow_constructor.hpp>
0049 #include <boost/type_traits/has_nothrow_copy.hpp>
0050 #include <boost/type_traits/is_nothrow_move_assignable.hpp>
0051 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
0052 #include <boost/type_traits/is_const.hpp>
0053 #include <boost/type_traits/is_same.hpp>
0054 #include <boost/type_traits/is_rvalue_reference.hpp>
0055 #include <boost/type_traits/is_constructible.hpp>
0056 #include <boost/type_traits/add_lvalue_reference.hpp>
0057 #include <boost/type_traits/declval.hpp>
0058 #include <boost/core/no_exceptions_support.hpp>
0059 #include <boost/core/enable_if.hpp>
0060 #include <boost/variant/recursive_wrapper_fwd.hpp>
0061 #include <boost/variant/static_visitor.hpp>
0062 
0063 #include <boost/mpl/assert.hpp>
0064 #include <boost/mpl/begin_end.hpp>
0065 #include <boost/mpl/bool.hpp>
0066 #include <boost/mpl/deref.hpp>
0067 #include <boost/mpl/empty.hpp>
0068 #include <boost/mpl/eval_if.hpp>
0069 #include <boost/mpl/find_if.hpp>
0070 #include <boost/mpl/fold.hpp>
0071 #include <boost/mpl/front.hpp>
0072 #include <boost/mpl/identity.hpp>
0073 #include <boost/mpl/if.hpp>
0074 #include <boost/mpl/insert_range.hpp>
0075 #include <boost/mpl/int.hpp>
0076 #include <boost/mpl/is_sequence.hpp>
0077 #include <boost/mpl/iterator_range.hpp>
0078 #include <boost/mpl/iter_fold_if.hpp>
0079 #include <boost/mpl/list.hpp>
0080 #include <boost/mpl/logical.hpp>
0081 #include <boost/mpl/max_element.hpp>
0082 #include <boost/mpl/next.hpp>
0083 #include <boost/mpl/not.hpp>
0084 #include <boost/mpl/pair.hpp>
0085 #include <boost/mpl/protect.hpp>
0086 #include <boost/mpl/push_front.hpp>
0087 #include <boost/mpl/same_as.hpp>
0088 #include <boost/mpl/size_t.hpp>
0089 #include <boost/mpl/sizeof.hpp>
0090 #include <boost/mpl/transform.hpp>
0091 
0092 ///////////////////////////////////////////////////////////////////////////////
0093 // Implementation Macros:
0094 //
0095 // BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
0096 //   Defined in boost/variant/detail/visitation_impl.hpp.
0097 //
0098 // BOOST_VARIANT_MINIMIZE_SIZE
0099 //   When #defined, implementation employs all known means to minimize the
0100 //   size of variant obje   cts. However, often unsuccessful due to alignment
0101 //   issues, and potentially harmful to runtime speed, so not enabled by
0102 //   default. (TODO: Investigate further.)
0103 
0104 #if defined(BOOST_VARIANT_MINIMIZE_SIZE)
0105 #   include <climits> // for SCHAR_MAX
0106 #   include <boost/mpl/eval_if.hpp>
0107 #   include <boost/mpl/equal_to.hpp>
0108 #   include <boost/mpl/identity.hpp>
0109 #   include <boost/mpl/int.hpp>
0110 #   include <boost/mpl/if.hpp>
0111 #   include <boost/mpl/less.hpp>
0112 #   include <boost/mpl/long.hpp>
0113 #   include <boost/mpl/O1_size.hpp>
0114 #endif
0115 
0116 
0117 namespace boost {
0118 
0119 namespace detail { namespace variant {
0120 
0121 ///////////////////////////////////////////////////////////////////////////////
0122 // (detail) metafunction max_value
0123 //
0124 // Finds the maximum value of the unary metafunction F over Sequence.
0125 //
0126 template <typename Sequence, typename F>
0127 struct max_value
0128 {
0129 private: // helpers, for metafunction result (below)
0130 
0131     typedef typename mpl::transform1<Sequence, F>::type transformed_;
0132     typedef typename mpl::max_element<transformed_
0133 
0134         >::type max_it;
0135 
0136 public: // metafunction result
0137 
0138     typedef typename mpl::deref<max_it>::type
0139         type;
0140 
0141 };
0142 
0143 struct add_alignment
0144 {
0145     template <typename State, typename Item>
0146     struct apply
0147         : mpl::size_t<
0148               ::boost::integer::static_lcm<
0149                   BOOST_MPL_AUX_VALUE_WKND(State)::value
0150                 , ::boost::alignment_of<Item>::value
0151                 >::value
0152             >
0153     {};
0154 };
0155 
0156 ///////////////////////////////////////////////////////////////////////////////
0157 // (detail) metafunction find_fallback_type
0158 //
0159 // Provides a fallback (i.e., nothrow default-constructible) type from the
0160 // specified sequence, or no_fallback_type if not found.
0161 //
0162 // This implementation is designed to prefer boost::blank over other potential
0163 // fallback types, regardless of its position in the specified sequence.
0164 //
0165 
0166 class no_fallback_type;
0167 
0168 struct find_fallback_type_pred
0169 {
0170     template <typename Iterator>
0171     struct apply
0172     {
0173     private:
0174         typedef typename mpl::deref<Iterator>::type t_;
0175 
0176     public:
0177         typedef mpl::not_< has_nothrow_constructor<t_> > type;
0178     };
0179 };
0180 
0181 template <typename Types>
0182 struct find_fallback_type
0183 {
0184 private: // helpers, for metafunction result (below)
0185 
0186     typedef typename mpl::end<Types>::type end_it;
0187 
0188     // [Find the first suitable fallback type...]
0189 
0190     typedef typename mpl::iter_fold_if<
0191           Types
0192         , mpl::int_<0>, mpl::protect< mpl::next<> >
0193         , mpl::protect< find_fallback_type_pred >
0194         >::type first_result_;
0195 
0196     typedef typename first_result_::first first_result_index;
0197     typedef typename first_result_::second first_result_it;
0198 
0199     // [...now search the rest of the sequence for boost::blank...]
0200 
0201     typedef typename mpl::iter_fold_if<
0202           mpl::iterator_range< first_result_it,end_it >
0203         , first_result_index, mpl::protect< mpl::next<> >
0204         , mpl::protect< mpl::not_same_as<boost::blank> >
0205         >::type second_result_;
0206 
0207     typedef typename second_result_::second second_result_it;
0208 
0209 public: // metafunction result
0210 
0211     // [...and return the results of the search:]
0212     typedef typename mpl::eval_if<
0213           is_same< second_result_it,end_it >
0214         , mpl::if_<
0215               is_same< first_result_it,end_it >
0216             , mpl::pair< no_fallback_type,no_fallback_type >
0217             , first_result_
0218             >
0219         , mpl::identity< second_result_ >
0220         >::type type;
0221 
0222 };
0223 
0224 ///////////////////////////////////////////////////////////////////////////////
0225 // (detail) metafunction is_variant_move_noexcept_constructible
0226 //
0227 // Returns true_type if all the types are nothrow move constructible.
0228 //
0229 template <class Types>
0230 struct is_variant_move_noexcept_constructible {
0231     typedef typename boost::mpl::find_if<
0232         Types, mpl::not_<boost::is_nothrow_move_constructible<boost::mpl::_1> >
0233     >::type iterator_t;
0234 
0235     typedef typename boost::mpl::end<Types>::type end_t;
0236     typedef typename boost::is_same<
0237         iterator_t, end_t
0238     >::type type;
0239 };
0240 
0241 ///////////////////////////////////////////////////////////////////////////////
0242 // (detail) metafunction is_variant_move_noexcept_assignable
0243 //
0244 // Returns true_type if all the types are nothrow move constructible.
0245 //
0246 template <class Types>
0247 struct is_variant_move_noexcept_assignable {
0248     typedef typename boost::mpl::find_if<
0249         Types, mpl::not_<boost::is_nothrow_move_assignable<boost::mpl::_1> >
0250     >::type iterator_t;
0251 
0252     typedef typename boost::mpl::end<Types>::type end_t;
0253     typedef typename boost::is_same<
0254         iterator_t, end_t
0255     >::type type;
0256 };
0257 
0258 ///////////////////////////////////////////////////////////////////////////////
0259 // (detail) metafunction is_variant_constructible_from
0260 //
0261 // Derives from true_type if at least one variant's type is constructible from T.
0262 //
0263 template <class T1, class T2>
0264 struct is_constructible_ext:
0265     boost::mpl::or_<
0266         boost::is_constructible<
0267             T1,
0268             T2
0269         >,
0270         boost::is_constructible<
0271             T1,
0272             typename boost::add_lvalue_reference<T2>::type
0273         >
0274     >
0275 {};
0276 
0277 template <class T, class Types>
0278 struct is_variant_constructible_from:
0279     boost::mpl::not_< boost::is_same<
0280         typename boost::mpl::find_if<
0281             Types,
0282             is_constructible_ext<boost::mpl::_1, T>
0283         >::type,
0284         typename boost::mpl::end<Types>::type
0285     > >
0286 {};
0287 
0288 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
0289 struct is_variant_constructible_from< boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >:
0290     boost::is_same<
0291         typename boost::mpl::find_if<
0292             typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::recursive_enabled_types,
0293             mpl::not_< is_variant_constructible_from< boost::mpl::_1, Types> >
0294         >::type,
0295         typename boost::mpl::end< typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::recursive_enabled_types >::type
0296     >
0297 {};
0298 
0299 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
0300 struct is_variant_constructible_from< const boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& , Types >:
0301     is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >
0302 {};
0303 
0304 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
0305 struct is_variant_constructible_from< boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& , Types >:
0306     is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >
0307 {};
0308 
0309 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
0310 struct is_variant_constructible_from< boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>&& , Types >:
0311     is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >
0312 {};
0313 
0314 template <BOOST_VARIANT_ENUM_PARAMS(typename T), class Types>
0315 struct is_variant_constructible_from< boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const && , Types >:
0316     is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Types >
0317 {};
0318 
0319 
0320 ///////////////////////////////////////////////////////////////////////////////
0321 // (detail) metafunction make_storage
0322 //
0323 // Provides an aligned storage type capable of holding any of the types
0324 // specified in the given type-sequence.
0325 //
0326 
0327 template <typename Types, typename NeverUsesBackupFlag>
0328 struct make_storage
0329 {
0330 private: // helpers, for metafunction result (below)
0331 
0332     typedef typename mpl::eval_if<
0333           NeverUsesBackupFlag
0334         , mpl::identity< Types >
0335         , mpl::push_front<
0336               Types, backup_holder<void*>
0337             >
0338         >::type types;
0339 
0340     typedef typename max_value<
0341           types, mpl::sizeof_<mpl::_1>
0342         >::type max_size;
0343 
0344 #if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0551))
0345 
0346     typedef typename mpl::fold<
0347           types
0348         , mpl::size_t<1>
0349         , add_alignment
0350         >::type max_alignment;
0351 
0352 #else // borland
0353 
0354     // temporary workaround -- use maximal alignment
0355     typedef mpl::size_t< -1 > max_alignment;
0356 
0357 #endif // borland workaround
0358 
0359 public: // metafunction result
0360 
0361     typedef ::boost::aligned_storage<
0362           BOOST_MPL_AUX_VALUE_WKND(max_size)::value
0363         , BOOST_MPL_AUX_VALUE_WKND(max_alignment)::value
0364         > type;
0365 };
0366 
0367 ///////////////////////////////////////////////////////////////////////////////
0368 // (detail) class destroyer
0369 //
0370 // Internal visitor that destroys the value it visits.
0371 //
0372 struct destroyer
0373     : public static_visitor<>
0374 {
0375 public: // visitor interfaces
0376 
0377     template <typename T>
0378     void internal_visit(T& operand, int) const BOOST_NOEXCEPT
0379     {
0380         operand.~T(); // must be noexcept
0381 
0382 #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0551)) || \
0383     BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
0384         (void)operand; // suppresses warnings
0385 #endif
0386     }
0387 
0388 };
0389 
0390 ///////////////////////////////////////////////////////////////////////////////
0391 // (detail) class template known_get
0392 //
0393 // Visitor that returns a reference to content of the specified type.
0394 //
0395 // Precondition: visited variant MUST contain logical content of type T.
0396 //
0397 template <typename T>
0398 class known_get
0399     : public static_visitor<T&>
0400 {
0401 
0402 public: // visitor interface
0403 
0404     T& operator()(T& operand) const BOOST_NOEXCEPT
0405     {
0406         return operand;
0407     }
0408 
0409     template <typename U>
0410     T& operator()(U&) const
0411     {
0412         // logical error to be here: see precondition above
0413         return ::boost::detail::variant::forced_return< T& >();
0414     }
0415 };
0416 
0417 ///////////////////////////////////////////////////////////////////////////////
0418 // (detail) class copy_into
0419 //
0420 // Internal visitor that copies the value it visits into the given buffer.
0421 //
0422 class copy_into
0423     : public static_visitor<>
0424 {
0425 private: // representation
0426 
0427     void* storage_;
0428 
0429 public: // structors
0430 
0431     explicit copy_into(void* storage) BOOST_NOEXCEPT
0432         : storage_(storage)
0433     {
0434     }
0435 
0436 public: // internal visitor interface
0437 
0438     template <typename T>
0439     void internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
0440     {
0441         new(storage_) T( operand.get() );
0442     }
0443 
0444     template <typename T>
0445     void internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
0446     {
0447         new(storage_) T( operand.get() );
0448     }
0449 
0450     template <typename T>
0451     void internal_visit(const T& operand, int) const
0452     {
0453         new(storage_) T(operand);
0454     }
0455 
0456 };
0457 
0458 ///////////////////////////////////////////////////////////////////////////////
0459 // (detail) class move_into
0460 //
0461 // Internal visitor that moves the value it visits into the given buffer.
0462 //
0463 class move_into
0464     : public static_visitor<>
0465 {
0466 private: // representation
0467 
0468     void* storage_;
0469 
0470 public: // structors
0471 
0472     explicit move_into(void* storage) BOOST_NOEXCEPT
0473         : storage_(storage)
0474     {
0475     }
0476 
0477 public: // internal visitor interface
0478 
0479     template <typename T>
0480     void internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
0481     {
0482         new(storage_) T( ::boost::detail::variant::move(operand.get()) );
0483     }
0484 
0485     template <typename T>
0486     void internal_visit(T& operand, int) const BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(boost::declval<T>())))
0487     {
0488         new(storage_) T(::boost::detail::variant::move(operand));
0489     }
0490 };
0491 
0492 ///////////////////////////////////////////////////////////////////////////////
0493 // (detail) class assign_storage
0494 //
0495 // Internal visitor that assigns the given storage (which must be a
0496 // constructed value of the same type) to the value it visits.
0497 //
0498 struct assign_storage
0499     : public static_visitor<>
0500 {
0501 private: // representation
0502 
0503     const void* rhs_storage_;
0504 
0505 public: // structors
0506 
0507     explicit assign_storage(const void* rhs_storage) BOOST_NOEXCEPT
0508         : rhs_storage_(rhs_storage)
0509     {
0510     }
0511 
0512 public: // internal visitor interfaces
0513 
0514     template <typename T>
0515     void internal_visit(backup_holder<T>& lhs_content, long) const
0516     {
0517         lhs_content.get()
0518             = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
0519     }
0520 
0521     template <typename T>
0522     void internal_visit(const backup_holder<T>& lhs_content, long) const
0523     {
0524         lhs_content.get()
0525             = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
0526     }
0527 
0528     template <typename T>
0529     void internal_visit(T& lhs_content, int) const
0530     {
0531         // NOTE TO USER :
0532         // Compile error here indicates one of variant's bounded types does
0533         // not meet the requirements of the Assignable concept. Thus,
0534         // variant is not Assignable.
0535         //
0536         // Hint: Are any of the bounded types const-qualified or references?
0537         //
0538         lhs_content = *static_cast< const T* >(rhs_storage_);
0539     }
0540 
0541 };
0542 
0543 ///////////////////////////////////////////////////////////////////////////////
0544 // (detail) class move_storage
0545 //
0546 // Internal visitor that moves the given storage (which must be a
0547 // constructed value of the same type) to the value it visits.
0548 //
0549 struct move_storage
0550     : public static_visitor<>
0551 {
0552 private: // representation
0553 
0554     void* rhs_storage_;
0555 
0556 public: // structors
0557 
0558     explicit move_storage(void* rhs_storage) BOOST_NOEXCEPT
0559         : rhs_storage_(rhs_storage)
0560     {
0561     }
0562 
0563 public: // internal visitor interfaces
0564 
0565     template <typename T>
0566     void internal_visit(backup_holder<T>& lhs_content, long) const
0567     {
0568         lhs_content.get()
0569             = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
0570     }
0571 
0572     template <typename T>
0573     void internal_visit(const backup_holder<T>& lhs_content, long) const
0574     {
0575         lhs_content.get()
0576             = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
0577     }
0578 
0579     template <typename T>
0580     void internal_visit(T& lhs_content, int) const
0581     {
0582         // NOTE TO USER :
0583         // Compile error here indicates one of variant's bounded types does
0584         // not meet the requirements of the Assignable concept. Thus,
0585         // variant is not Assignable.
0586         //
0587         // Hint: Are any of the bounded types const-qualified or references?
0588         //
0589         lhs_content = ::boost::detail::variant::move(*static_cast<T* >(rhs_storage_));
0590     }
0591 
0592 };
0593 
0594 ///////////////////////////////////////////////////////////////////////////////
0595 // (detail) class direct_assigner
0596 //
0597 // Generic static visitor that: if and only if the visited value is of the
0598 // specified type, assigns the given value to the visited value and returns
0599 // true; else returns false.
0600 //
0601 template <typename T>
0602 class direct_assigner
0603     : public static_visitor<bool>
0604 {
0605 private: // representation
0606 
0607     const T& rhs_;
0608 
0609 public: // structors
0610 
0611     explicit direct_assigner(const T& rhs) BOOST_NOEXCEPT
0612         : rhs_(rhs)
0613     {
0614     }
0615 
0616 public: // visitor interface
0617 
0618     bool operator()(T& lhs)
0619     {
0620         lhs = rhs_;
0621         return true;
0622     }
0623 
0624     template <typename U>
0625     bool operator()(U&) BOOST_NOEXCEPT
0626     {
0627         return false;
0628     }
0629 
0630 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
0631 private:
0632     // silence MSVC warning C4512: assignment operator could not be generated
0633     direct_assigner& operator= (direct_assigner const&);
0634 #endif
0635 };
0636 
0637 ///////////////////////////////////////////////////////////////////////////////
0638 // (detail) class direct_mover
0639 //
0640 // Generic static visitor that: if and only if the visited value is of the
0641 // specified type, move assigns the given value to the visited value and returns
0642 // true; else returns false.
0643 //
0644 template <typename T>
0645 class direct_mover
0646     : public static_visitor<bool>
0647 {
0648 private: // representation
0649 
0650     T& rhs_;
0651 
0652 public: // structors
0653 
0654     explicit direct_mover(T& rhs) BOOST_NOEXCEPT
0655         : rhs_(rhs)
0656     {
0657     }
0658 
0659 public: // visitor interface
0660 
0661     bool operator()(T& lhs)
0662     {
0663         lhs = ::boost::detail::variant::move(rhs_);
0664         return true;
0665     }
0666 
0667     template <typename U>
0668     bool operator()(U&) BOOST_NOEXCEPT
0669     {
0670         return false;
0671     }
0672 
0673 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
0674 private:
0675     // silence MSVC warning C4512: assignment operator could not be generated
0676     direct_mover& operator= (direct_mover const&);
0677 #endif
0678 };
0679 
0680 
0681 ///////////////////////////////////////////////////////////////////////////////
0682 // (detail) class backup_assigner
0683 //
0684 // Internal visitor that "assigns" the given value to the visited value,
0685 // using backup to recover if the destroy-copy sequence fails.
0686 //
0687 // NOTE: This needs to be a friend of variant, as it needs access to
0688 // indicate_which, indicate_backup_which, etc.
0689 //
0690 template <typename Variant>
0691 class backup_assigner
0692     : public static_visitor<>
0693 {
0694 private: // representation
0695 
0696     Variant& lhs_;
0697     int rhs_which_;
0698     const void* rhs_content_;
0699     void (*copy_rhs_content_)(void*, const void*);
0700 
0701 public: // structors
0702 
0703     template<class RhsT>
0704     backup_assigner(Variant& lhs, int rhs_which, const RhsT& rhs_content)
0705         : lhs_(lhs)
0706         , rhs_which_(rhs_which)
0707         , rhs_content_(&rhs_content)
0708         , copy_rhs_content_(&construct_impl<RhsT>)
0709     {
0710     }
0711 
0712 private: // helpers, for visitor interface (below)
0713 
0714     template<class RhsT>
0715     static void construct_impl(void* addr, const void* obj)
0716     {
0717         new(addr) RhsT(*static_cast<const RhsT*>(obj));
0718     }
0719 
0720     template <typename LhsT>
0721     void backup_assign_impl(
0722           backup_holder<LhsT>& lhs_content
0723         , mpl::false_ // is_nothrow_move_constructible
0724         , long
0725         )
0726     {
0727         // Move lhs content to backup...
0728         backup_holder<LhsT> backup_lhs_content(0);
0729         backup_lhs_content.swap(lhs_content); // nothrow
0730 
0731         // ...destroy lhs content...
0732         lhs_content.~backup_holder<LhsT>(); // nothrow
0733 
0734         BOOST_TRY
0735         {
0736             // ...and attempt to copy rhs content into lhs storage:
0737             copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
0738         }
0739         BOOST_CATCH (...)
0740         {
0741             // In case of failure, copy backup pointer to lhs storage...
0742             new(lhs_.storage_.address())
0743                     backup_holder<LhsT>( 0 ); // nothrow
0744 
0745             static_cast<backup_holder<LhsT>* >(lhs_.storage_.address())
0746                     ->swap(backup_lhs_content); // nothrow
0747 
0748             // ...and rethrow:
0749             BOOST_RETHROW;
0750         }
0751         BOOST_CATCH_END
0752 
0753         // In case of success, indicate new content type:
0754         lhs_.indicate_which(rhs_which_); // nothrow
0755     }
0756 
0757     template <typename LhsT>
0758     void backup_assign_impl(
0759           LhsT& lhs_content
0760         , mpl::true_ // is_nothrow_move_constructible
0761         , int
0762         )
0763     {
0764         // Move lhs content to backup...
0765         LhsT backup_lhs_content(
0766               ::boost::detail::variant::move(lhs_content)
0767             ); // nothrow
0768 
0769         // ...destroy lhs content...
0770         lhs_content.~LhsT(); // nothrow
0771 
0772         BOOST_TRY
0773         {
0774             // ...and attempt to copy rhs content into lhs storage:
0775             copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
0776         }
0777         BOOST_CATCH (...)
0778         {
0779             // In case of failure, restore backup content to lhs storage...
0780             new(lhs_.storage_.address())
0781                 LhsT(
0782                       ::boost::detail::variant::move(backup_lhs_content)
0783                     ); // nothrow
0784 
0785             // ...and rethrow:
0786             BOOST_RETHROW;
0787         }
0788         BOOST_CATCH_END
0789 
0790         // In case of success, indicate new content type:
0791         lhs_.indicate_which(rhs_which_); // nothrow
0792     }
0793 
0794     template <typename LhsT>
0795     void backup_assign_impl(
0796           LhsT& lhs_content
0797         , mpl::false_ // is_nothrow_move_constructible
0798         , int
0799         )
0800     {
0801         // Backup lhs content...
0802         LhsT* backup_lhs_ptr = new LhsT(lhs_content);
0803 
0804         // ...destroy lhs content...
0805         lhs_content.~LhsT(); // nothrow
0806 
0807         BOOST_TRY
0808         {
0809             // ...and attempt to copy rhs content into lhs storage:
0810             copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
0811         }
0812         BOOST_CATCH (...)
0813         {
0814             // In case of failure, copy backup pointer to lhs storage...
0815             new(lhs_.storage_.address())
0816                 backup_holder<LhsT>( backup_lhs_ptr ); // nothrow
0817 
0818             // ...indicate now using backup...
0819             lhs_.indicate_backup_which( lhs_.which() ); // nothrow
0820 
0821             // ...and rethrow:
0822             BOOST_RETHROW;
0823         }
0824         BOOST_CATCH_END
0825 
0826         // In case of success, indicate new content type...
0827         lhs_.indicate_which(rhs_which_); // nothrow
0828 
0829         // ...and delete backup:
0830         delete backup_lhs_ptr; // nothrow
0831     }
0832 
0833 public: // visitor interface
0834 
0835     template <typename LhsT>
0836     void internal_visit(LhsT& lhs_content, int)
0837     {
0838         typedef typename is_nothrow_move_constructible<LhsT>::type
0839             nothrow_move;
0840 
0841         backup_assign_impl( lhs_content, nothrow_move(), 1L);
0842     }
0843 
0844 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
0845 private:
0846     // silence MSVC warning C4512: assignment operator could not be generated
0847     backup_assigner& operator= (backup_assigner const&);
0848 #endif
0849 };
0850 
0851 ///////////////////////////////////////////////////////////////////////////////
0852 // (detail) class swap_with
0853 //
0854 // Visitor that swaps visited value with content of given variant.
0855 //
0856 // Precondition: Given variant MUST have same logical type as visited value.
0857 //
0858 template <typename Variant>
0859 struct swap_with
0860     : public static_visitor<>
0861 {
0862 private: // representation
0863 
0864     Variant& toswap_;
0865 
0866 public: // structors
0867 
0868     explicit swap_with(Variant& toswap) BOOST_NOEXCEPT
0869         : toswap_(toswap)
0870     {
0871     }
0872 
0873 public: // internal visitor interfaces
0874 
0875     template <typename T>
0876     void operator()(T& operand) const
0877     {
0878         // Since the precondition ensures types are same, get T...
0879         known_get<T> getter;
0880         T& other = toswap_.apply_visitor(getter);
0881 
0882         // ...and swap:
0883         ::boost::detail::variant::move_swap( operand, other );
0884     }
0885 
0886 private:
0887     swap_with& operator=(const swap_with&);
0888 
0889 };
0890 
0891 ///////////////////////////////////////////////////////////////////////////////
0892 // (detail) class reflect
0893 //
0894 // Generic static visitor that performs a typeid on the value it visits.
0895 //
0896 
0897 class reflect
0898     : public static_visitor<const boost::typeindex::type_info&>
0899 {
0900 public: // visitor interfaces
0901 
0902     template <typename T>
0903     const boost::typeindex::type_info& operator()(const T&) const BOOST_NOEXCEPT
0904     {
0905         return boost::typeindex::type_id<T>().type_info();
0906     }
0907 
0908 };
0909 
0910 ///////////////////////////////////////////////////////////////////////////////
0911 // (detail) class comparer
0912 //
0913 // Generic static visitor that compares the content of the given lhs variant
0914 // with the visited rhs content using Comp.
0915 //
0916 // Precondition: lhs.which() == rhs.which()
0917 //
0918 template <typename Variant, typename Comp>
0919 class comparer
0920     : public static_visitor<bool>
0921 {
0922 private: // representation
0923 
0924     const Variant& lhs_;
0925 
0926 public: // structors
0927 
0928     explicit comparer(const Variant& lhs) BOOST_NOEXCEPT
0929         : lhs_(lhs)
0930     {
0931     }
0932 
0933 public: // visitor interfaces
0934 
0935     template <typename T>
0936     bool operator()(T& rhs_content) const
0937     {
0938         // Since the precondition ensures lhs and rhs types are same, get T...
0939         known_get<T> getter;
0940         const T& lhs_content = lhs_.apply_visitor(getter);
0941 
0942         // ...and compare lhs and rhs contents:
0943         return Comp()(lhs_content, rhs_content);
0944     }
0945 
0946 private:
0947     comparer& operator=(const comparer&);
0948 
0949 };
0950 
0951 ///////////////////////////////////////////////////////////////////////////////
0952 // (detail) class equal_comp
0953 //
0954 // Generic function object compares lhs with rhs using operator==.
0955 //
0956 struct equal_comp
0957 {
0958     template <typename T>
0959     bool operator()(const T& lhs, const T& rhs) const
0960     {
0961         return lhs == rhs;
0962     }
0963 };
0964 
0965 ///////////////////////////////////////////////////////////////////////////////
0966 // (detail) class less_comp
0967 //
0968 // Generic function object compares lhs with rhs using operator<.
0969 //
0970 struct less_comp
0971 {
0972     template <typename T>
0973     bool operator()(const T& lhs, const T& rhs) const
0974     {
0975         return lhs < rhs;
0976     }
0977 };
0978 
0979 ///////////////////////////////////////////////////////////////////////////////
0980 // (detail) class template invoke_visitor
0981 //
0982 // Internal visitor that invokes the given visitor using:
0983 //  * for wrappers (e.g., recursive_wrapper), the wrapper's held value.
0984 //  * for all other values, the value itself.
0985 //
0986 template <typename Visitor, bool MoveSemantics>
0987 class invoke_visitor
0988 {
0989 private: // representation
0990 
0991     Visitor& visitor_;
0992 
0993 public: // visitor typedefs
0994 
0995     typedef typename Visitor::result_type
0996         result_type;
0997 
0998 public: // structors
0999 
1000     explicit invoke_visitor(Visitor& visitor) BOOST_NOEXCEPT
1001         : visitor_(visitor)
1002     {
1003     }
1004 
1005 public: // internal visitor interfaces
1006 
1007     //using workaround with is_same<T, T> to prenvent compilation error, because we need to use T in enable_if to make SFINAE work
1008     template <typename T>
1009     typename enable_if_c<MoveSemantics && is_same<T, T>::value, result_type>::type internal_visit(T&& operand, int)
1010     {
1011         return visitor_(std::move(operand));
1012     }
1013 
1014     //using workaround with is_same<T, T> to prenvent compilation error, because we need to use T in enable_if to make SFINAE work
1015     template <typename T>
1016     typename disable_if_c<MoveSemantics && is_same<T, T>::value, result_type>::type internal_visit(T&& operand, int)
1017     {
1018         return visitor_(operand);
1019     }
1020 
1021 public: // internal visitor interfaces, cont.
1022 
1023     template <typename T>
1024     result_type internal_visit(boost::recursive_wrapper<T>& operand, long)
1025     {
1026         return internal_visit( operand.get(), 1L );
1027     }
1028 
1029     template <typename T>
1030     result_type internal_visit(const boost::recursive_wrapper<T>& operand, long)
1031     {
1032         return internal_visit( operand.get(), 1L );
1033     }
1034 
1035     template <typename T>
1036     result_type internal_visit(boost::detail::reference_content<T>& operand, long)
1037     {
1038         return internal_visit( operand.get(), 1L );
1039     }
1040 
1041     template <typename T>
1042     result_type internal_visit(const boost::detail::reference_content<T>& operand, long)
1043     {
1044         return internal_visit( operand.get(), 1L );
1045     }
1046 
1047     template <typename T>
1048     result_type internal_visit(boost::detail::variant::backup_holder<T>& operand, long)
1049     {
1050         return internal_visit( operand.get(), 1L );
1051     }
1052 
1053     template <typename T>
1054     result_type internal_visit(const boost::detail::variant::backup_holder<T>& operand, long)
1055     {
1056         return internal_visit( operand.get(), 1L );
1057     }
1058 
1059 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
1060 private:
1061     // silence MSVC warning C4512: assignment operator could not be generated
1062     invoke_visitor& operator= (invoke_visitor const&);
1063 #endif
1064 };
1065 
1066 }} // namespace detail::variant
1067 
1068 ///////////////////////////////////////////////////////////////////////////////
1069 // class template variant (concept inspired by Andrei Alexandrescu)
1070 //
1071 // See docs and boost/variant/variant_fwd.hpp for more information.
1072 //
1073 template <
1074       typename T0_
1075     , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)
1076     >
1077 class variant
1078 {
1079 private: // helpers, for typedefs (below)
1080 
1081     typedef variant wknd_self_t;
1082 
1083     struct is_recursive_
1084         : detail::variant::is_recursive_flag<T0_>
1085     {
1086     };
1087 
1088     typedef typename mpl::eval_if<
1089           is_recursive_
1090         , T0_
1091         , mpl::identity< T0_ >
1092         >::type unwrapped_T0_;
1093 
1094     struct is_sequence_based_
1095         : detail::variant::is_over_sequence<unwrapped_T0_>
1096     {
1097     };
1098 
1099 #if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
1100 
1101 private: // helpers, for typedefs (below)
1102 
1103     typedef typename mpl::eval_if<
1104           is_sequence_based_
1105         , unwrapped_T0_ // over_sequence<...>::type
1106         , detail::variant::make_variant_list<
1107               unwrapped_T0_
1108             , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
1109             >
1110         >::type specified_types;
1111 
1112     BOOST_STATIC_ASSERT((
1113           ::boost::mpl::not_< mpl::empty<specified_types> >::value
1114         ));
1115 
1116 public: // public typedefs
1117     typedef typename mpl::eval_if<
1118           is_recursive_
1119         , mpl::transform<
1120               specified_types
1121             , mpl::protect<
1122                   detail::variant::quoted_enable_recursive<wknd_self_t>
1123                 >
1124             >
1125         , mpl::identity< specified_types >
1126         >::type recursive_enabled_types;    // used by is_variant_constructible_from<> trait
1127 
1128     typedef typename mpl::transform<
1129           recursive_enabled_types
1130         , unwrap_recursive<mpl::_1>
1131         >::type types;
1132 
1133 private: // internal typedefs
1134 
1135     typedef typename mpl::transform<
1136           recursive_enabled_types
1137         , mpl::protect< detail::make_reference_content<> >
1138         >::type internal_types;
1139 
1140     typedef typename mpl::front<
1141           internal_types
1142         >::type internal_T0;
1143 
1144 #else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
1145 
1146 private: // helpers, for typedefs (below)
1147 
1148     typedef unwrapped_T0_ T0;
1149 
1150     #define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
1151         typedef typename mpl::eval_if< \
1152               is_recursive_ \
1153             , detail::variant::enable_recursive< \
1154                   BOOST_PP_CAT(T,N) \
1155                 , wknd_self_t \
1156                 > \
1157             , mpl::identity< BOOST_PP_CAT(T,N) > \
1158             >::type BOOST_PP_CAT(recursive_enabled_T,N); \
1159         /**/
1160 
1161     BOOST_PP_REPEAT(
1162           BOOST_VARIANT_LIMIT_TYPES
1163         , BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1164         , _
1165         )
1166 
1167     #undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
1168 
1169     #define BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS(z,N,_) \
1170         typedef typename unwrap_recursive< \
1171               BOOST_PP_CAT(recursive_enabled_T,N) \
1172             >::type BOOST_PP_CAT(public_T,N); \
1173         /**/
1174 
1175     BOOST_PP_REPEAT(
1176           BOOST_VARIANT_LIMIT_TYPES
1177         , BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1178         , _
1179         )
1180 
1181     #undef BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
1182 
1183 public: // public typedefs
1184 
1185     typedef typename detail::variant::make_variant_list<
1186           BOOST_VARIANT_ENUM_PARAMS(public_T)
1187         >::type types;
1188 
1189 private: // helpers, for internal typedefs (below)
1190 
1191     #define BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS(z,N,_) \
1192         typedef detail::make_reference_content< \
1193               BOOST_PP_CAT(recursive_enabled_T,N) \
1194             >::type BOOST_PP_CAT(internal_T,N); \
1195         /**/
1196 
1197     BOOST_PP_REPEAT(
1198           BOOST_VARIANT_LIMIT_TYPES
1199         , BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1200         , _
1201         )
1202 
1203     #undef BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
1204 
1205 private: // internal typedefs
1206 
1207     typedef typename detail::variant::make_variant_list<
1208           BOOST_VARIANT_ENUM_PARAMS(internal_T)
1209         >::type internal_types;
1210 
1211 private: // static precondition assertions
1212 
1213     // NOTE TO USER :
1214     // variant< type-sequence > syntax is not supported on this compiler!
1215     //
1216     BOOST_MPL_ASSERT_NOT(( is_sequence_based_ ));
1217 
1218 #endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT workaround
1219 
1220 private: // helpers, for representation (below)
1221 
1222     typedef typename detail::variant::find_fallback_type<
1223           internal_types
1224         >::type fallback_type_result_;
1225 
1226     typedef typename fallback_type_result_::first
1227         fallback_type_index_;
1228     typedef typename fallback_type_result_::second
1229         fallback_type_;
1230 
1231     struct has_fallback_type_
1232         : mpl::not_<
1233               is_same< fallback_type_, detail::variant::no_fallback_type >
1234             >
1235     {
1236     };
1237 
1238     typedef has_fallback_type_
1239         never_uses_backup_flag;
1240 
1241     typedef typename detail::variant::make_storage<
1242           internal_types, never_uses_backup_flag
1243         >::type storage_t;
1244 
1245     typedef typename detail::variant::is_variant_move_noexcept_constructible<
1246         internal_types
1247     > variant_move_noexcept_constructible;
1248 
1249     typedef typename detail::variant::is_variant_move_noexcept_assignable<
1250         internal_types
1251     > variant_move_noexcept_assignable;
1252 
1253 private: // helpers, for representation (below)
1254 
1255     // which_ on:
1256     // * [0,  size<internal_types>) indicates stack content
1257     // * [-size<internal_types>, 0) indicates pointer to heap backup
1258     // if which_ >= 0:
1259     // * then which() -> which_
1260     // * else which() -> -(which_ + 1)
1261 
1262 #if !defined(BOOST_VARIANT_MINIMIZE_SIZE)
1263 
1264     typedef int which_t;
1265 
1266 #else // defined(BOOST_VARIANT_MINIMIZE_SIZE)
1267 
1268     // [if O1_size available, then attempt which_t size optimization...]
1269     // [select signed char if fewer than SCHAR_MAX types, else signed int:]
1270     typedef typename mpl::eval_if<
1271           mpl::equal_to< mpl::O1_size<internal_types>, mpl::long_<-1> >
1272         , mpl::identity< int >
1273         , mpl::if_<
1274               mpl::less< mpl::O1_size<internal_types>, mpl::int_<SCHAR_MAX> >
1275             , signed char
1276             , int
1277             >
1278         >::type which_t;
1279 
1280 #endif // BOOST_VARIANT_MINIMIZE_SIZE switch
1281 
1282 // representation -- private when possible
1283 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
1284     private:
1285 #else
1286     public:
1287 #endif
1288 
1289     which_t which_;
1290     storage_t storage_;
1291 
1292     void indicate_which(int which_arg) BOOST_NOEXCEPT
1293     {
1294         which_ = static_cast<which_t>( which_arg );
1295     }
1296 
1297     void indicate_backup_which(int which_arg) BOOST_NOEXCEPT
1298     {
1299         which_ = static_cast<which_t>( -(which_arg + 1) );
1300     }
1301 
1302 private: // helpers, for queries (below)
1303 
1304     bool using_backup() const BOOST_NOEXCEPT
1305     {
1306         return which_ < 0;
1307     }
1308 
1309 public: // queries
1310 
1311     int which() const BOOST_NOEXCEPT
1312     {
1313         // If using heap backup...
1314         if (using_backup())
1315             // ...then return adjusted which_:
1316             return -(which_ + 1);
1317 
1318         // Otherwise, return which_ directly:
1319         return which_;
1320     }
1321 
1322 private: // helpers, for structors (below)
1323 
1324     struct initializer
1325         : BOOST_VARIANT_AUX_INITIALIZER_T(
1326               recursive_enabled_types, recursive_enabled_T
1327             )
1328     {
1329     };
1330 
1331     void destroy_content() BOOST_NOEXCEPT
1332     {
1333         detail::variant::destroyer visitor;
1334         this->internal_apply_visitor(visitor);
1335     }
1336 
1337 public: // structors
1338 
1339     ~variant() BOOST_NOEXCEPT
1340     {
1341         destroy_content();
1342     }
1343 
1344     variant()
1345 #if !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130))
1346               BOOST_NOEXCEPT_IF(boost::has_nothrow_constructor<internal_T0>::value)
1347 #endif
1348     {
1349 #ifdef _MSC_VER
1350 #pragma warning( push )
1351 // behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized
1352 #pragma warning( disable : 4345 )
1353 #endif
1354         // NOTE TO USER :
1355         // Compile error from here indicates that the first bound
1356         // type is not default-constructible, and so variant cannot
1357         // support its own default-construction.
1358         //
1359         new( storage_.address() ) internal_T0();
1360         indicate_which(0); // zero is the index of the first bounded type
1361 #ifdef _MSC_VER
1362 #pragma warning( pop )
1363 #endif
1364     }
1365 
1366 private: // helpers, for structors, cont. (below)
1367 
1368     class convert_copy_into
1369         : public static_visitor<int>
1370     {
1371     private: // representation
1372 
1373         void* storage_;
1374 
1375     public: // structors
1376 
1377         explicit convert_copy_into(void* storage) BOOST_NOEXCEPT
1378             : storage_(storage)
1379         {
1380         }
1381 
1382     public: // internal visitor interfaces (below)
1383 
1384         template <typename T>
1385         int internal_visit(T& operand, int) const
1386         {
1387             // NOTE TO USER :
1388             // Compile error here indicates one of the source variant's types
1389             // cannot be unambiguously converted to the destination variant's
1390             // types (or that no conversion exists).
1391             //
1392             return initializer::initialize(storage_, operand);
1393         }
1394 
1395 #   if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0564))
1396         template <typename T>
1397         result_type internal_visit(const T& operand, int) const
1398         {
1399             return initializer::initialize(storage_, operand);
1400         }
1401 #   endif
1402 
1403         template <typename T>
1404         int internal_visit(boost::detail::reference_content<T>& operand, long) const
1405         {
1406             return internal_visit( operand.get(), 1L );
1407         }
1408 
1409         template <typename T>
1410         int internal_visit(const boost::detail::reference_content<T>& operand, long) const
1411         {
1412             return internal_visit( operand.get(), 1L );
1413         }
1414 
1415         template <typename T>
1416         int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
1417         {
1418             return internal_visit( operand.get(), 1L );
1419         }
1420 
1421         template <typename T>
1422         int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
1423         {
1424             return internal_visit( operand.get(), 1L );
1425         }
1426 
1427         template <typename T>
1428         int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1429         {
1430             return internal_visit( operand.get(), 1L );
1431         }
1432 
1433         template <typename T>
1434         int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
1435         {
1436             return internal_visit( operand.get(), 1L );
1437         }
1438 
1439     };
1440 
1441     friend class convert_copy_into;
1442 
1443     class convert_move_into
1444         : public static_visitor<int>
1445     {
1446     private: // representation
1447 
1448         void* storage_;
1449 
1450     public: // structors
1451 
1452         explicit convert_move_into(void* storage) BOOST_NOEXCEPT
1453             : storage_(storage)
1454         {
1455         }
1456 
1457     public: // internal visitor interfaces (below)
1458 
1459         template <typename T>
1460         int internal_visit(T& operand, int) const
1461         {
1462             // NOTE TO USER :
1463             // Compile error here indicates one of the source variant's types
1464             // cannot be unambiguously converted to the destination variant's
1465             // types (or that no conversion exists).
1466             //
1467             return initializer::initialize(storage_, detail::variant::move(operand) );
1468         }
1469 
1470         template <typename T>
1471         int internal_visit(boost::detail::reference_content<T>& operand, long) const
1472         {
1473             return internal_visit( operand.get(), 1L );
1474         }
1475 
1476         template <typename T>
1477         int internal_visit(const boost::detail::reference_content<T>& operand, long) const
1478         {
1479             return internal_visit( operand.get(), 1L );
1480         }
1481 
1482         template <typename T>
1483         int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
1484         {
1485             return internal_visit( operand.get(), 1L );
1486         }
1487 
1488         template <typename T>
1489         int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
1490         {
1491             return internal_visit( operand.get(), 1L );
1492         }
1493 
1494         template <typename T>
1495         int internal_visit(boost::recursive_wrapper<T>& operand, long) const
1496         {
1497             return internal_visit( operand.get(), 1L );
1498         }
1499 
1500         template <typename T>
1501         int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
1502         {
1503             return internal_visit( operand.get(), 1L );
1504         }
1505     };
1506 
1507     friend class convert_move_into;
1508 
1509 private: // helpers, for structors, below
1510 
1511     template <typename T>
1512     void convert_construct(
1513           T& operand
1514         , int
1515         , mpl::false_ = mpl::false_() // is_foreign_variant
1516         )
1517     {
1518         // NOTE TO USER :
1519         // Compile error here indicates that the given type is not
1520         // unambiguously convertible to one of the variant's types
1521         // (or that no conversion exists).
1522         //
1523         indicate_which(
1524               initializer::initialize(
1525                   storage_.address()
1526                 , operand
1527                 )
1528             );
1529     }
1530 
1531     template <typename T>
1532     typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type convert_construct(
1533           T&& operand
1534         , int
1535         , mpl::false_ = mpl::false_() // is_foreign_variant
1536         )
1537     {
1538         // NOTE TO USER :
1539         // Compile error here indicates that the given type is not
1540         // unambiguously convertible to one of the variant's types
1541         // (or that no conversion exists).
1542         //
1543         indicate_which(
1544               initializer::initialize(
1545                   storage_.address()
1546                 , detail::variant::move(operand)
1547                 )
1548             );
1549     }
1550 
1551     template <typename Variant>
1552     void convert_construct(
1553           Variant& operand
1554         , long
1555         , mpl::true_// is_foreign_variant
1556         )
1557     {
1558         convert_copy_into visitor(storage_.address());
1559         indicate_which(
1560               operand.internal_apply_visitor(visitor)
1561             );
1562     }
1563 
1564     template <typename Variant>
1565     typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct(
1566           Variant&& operand
1567         , long
1568         , mpl::true_// is_foreign_variant
1569         )
1570     {
1571         convert_move_into visitor(storage_.address());
1572         indicate_which(
1573               operand.internal_apply_visitor(visitor)
1574             );
1575     }
1576 
1577     template <typename Variant>
1578     void convert_construct_variant(Variant& operand)
1579     {
1580         // [Determine if the given variant is itself a bounded type, or if its
1581         //  content needs to be converted (i.e., it is a 'foreign' variant):]
1582         //
1583 
1584         typedef typename mpl::find_if<
1585               types
1586             , is_same<
1587                   add_const<mpl::_1>
1588                 , const Variant
1589                 >
1590             >::type found_it;
1591 
1592         typedef typename mpl::end<types>::type not_found;
1593         typedef typename is_same<
1594               found_it, not_found
1595             >::type is_foreign_variant;
1596 
1597         // Convert construct from operand:
1598         convert_construct(
1599               operand, 1L
1600             , is_foreign_variant()
1601             );
1602     }
1603 
1604     template <typename Variant>
1605     typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct_variant(Variant&& operand)
1606     {
1607         // [Determine if the given variant is itself a bounded type, or if its
1608         //  content needs to be converted (i.e., it is a 'foreign' variant):]
1609         //
1610 
1611         typedef typename mpl::find_if<
1612               types
1613             , is_same<
1614                   add_const<mpl::_1>
1615                 , const Variant
1616                 >
1617             >::type found_it;
1618 
1619         typedef typename mpl::end<types>::type not_found;
1620         typedef typename is_same<
1621               found_it, not_found
1622             >::type is_foreign_variant;
1623 
1624         // Convert move construct from operand:
1625         convert_construct(
1626               detail::variant::move(operand), 1L
1627             , is_foreign_variant()
1628             );
1629     }
1630 
1631     template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1632     typename boost::enable_if<mpl::or_<
1633         boost::is_same<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>, variant>,
1634         boost::detail::variant::is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&, internal_types>
1635     > >::type convert_construct(
1636           boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1637         , long
1638         )
1639     {
1640         convert_construct_variant(operand);
1641     }
1642 
1643     template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1644     typename boost::enable_if<mpl::or_<
1645         boost::is_same<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>, variant>,
1646         boost::detail::variant::is_variant_constructible_from<const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&, internal_types>
1647     > >::type convert_construct(
1648           const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
1649         , long
1650         )
1651     {
1652         convert_construct_variant(operand);
1653     }
1654 
1655     template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
1656     typename boost::enable_if<mpl::or_<
1657         boost::is_same<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>, variant>,
1658         boost::detail::variant::is_variant_constructible_from<boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&&, internal_types>
1659     > >::type convert_construct(
1660           boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&& operand
1661         , long
1662         )
1663     {
1664         convert_construct_variant( detail::variant::move(operand) );
1665     }
1666 
1667 public: // structors, cont.
1668 
1669     template <typename T>
1670     variant(const T& operand,
1671         typename boost::enable_if<mpl::or_<
1672             mpl::and_<
1673                 mpl::not_< boost::is_same<T, variant> >,
1674                 boost::detail::variant::is_variant_constructible_from<const T&, internal_types>
1675             >,
1676             boost::is_same<T, boost::recursive_variant_> >,
1677             bool >::type = true)
1678     {
1679         convert_construct(operand, 1L);
1680     }
1681 
1682     template <typename T>
1683     variant(
1684           T& operand
1685         , typename boost::enable_if<mpl::or_<
1686             mpl::and_<
1687                 mpl::not_< is_const<T> >,
1688                 mpl::not_< boost::is_same<T, variant> >,
1689                 boost::detail::variant::is_variant_constructible_from<T&, internal_types>
1690             >,
1691             boost::is_same<T, boost::recursive_variant_> >,
1692             bool >::type = true
1693         )
1694     {
1695         convert_construct(operand, 1L);
1696     }
1697 
1698     template <class T>
1699     variant(T&& operand,
1700         typename boost::enable_if<mpl::or_<
1701             mpl::and_<
1702                 boost::is_rvalue_reference<T&&>,
1703                 mpl::not_< boost::is_const<T> >,
1704                 mpl::not_< boost::is_same<T, variant> >,
1705                 boost::detail::variant::is_variant_constructible_from<T&&, internal_types>
1706             >,
1707             boost::is_same<T, boost::recursive_variant_> >,
1708             bool >::type = true)
1709     {
1710         convert_construct( detail::variant::move(operand), 1L);
1711     }
1712 
1713 public: // structors, cont.
1714 
1715     // [MSVC6 requires copy constructor appear after template constructors]
1716     variant(const variant& operand)
1717     {
1718         // Copy the value of operand into *this...
1719         detail::variant::copy_into visitor( storage_.address() );
1720         operand.internal_apply_visitor(visitor);
1721 
1722         // ...and activate the *this's primary storage on success:
1723         indicate_which(operand.which());
1724     }
1725 
1726     variant(variant&& operand) BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value)
1727     {
1728         // Move the value of operand into *this...
1729         detail::variant::move_into visitor( storage_.address() );
1730         operand.internal_apply_visitor(visitor);
1731 
1732         // ...and activate the *this's primary storage on success:
1733         indicate_which(operand.which());
1734     }
1735 
1736 private: // helpers, for modifiers (below)
1737 
1738     template <typename Variant>
1739     friend class detail::variant::backup_assigner;
1740 
1741     // class assigner
1742     //
1743     // Internal visitor that "assigns" the visited value to the given variant
1744     // by appropriate destruction and copy-construction.
1745     //
1746 
1747     class assigner
1748         : public static_visitor<>
1749     {
1750     protected: // representation
1751 
1752         variant& lhs_;
1753         const int rhs_which_;
1754 
1755     public: // structors
1756 
1757         assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
1758             : lhs_(lhs)
1759             , rhs_which_(rhs_which)
1760         {
1761         }
1762 
1763     protected: // helpers, for internal visitor interface (below)
1764 
1765         template <typename RhsT, typename B1, typename B2>
1766         void assign_impl(
1767               const RhsT& rhs_content
1768             , mpl::true_ // has_nothrow_copy
1769             , B1 // is_nothrow_move_constructible
1770             , B2 // has_fallback_type
1771             ) const BOOST_NOEXCEPT
1772         {
1773             // Destroy lhs's content...
1774             lhs_.destroy_content(); // nothrow
1775 
1776             // ...copy rhs content into lhs's storage...
1777             new(lhs_.storage_.address())
1778                 RhsT( rhs_content ); // nothrow
1779 
1780             // ...and indicate new content type:
1781             lhs_.indicate_which(rhs_which_); // nothrow
1782         }
1783 
1784         template <typename RhsT, typename B>
1785         void assign_impl(
1786               const RhsT& rhs_content
1787             , mpl::false_ // has_nothrow_copy
1788             , mpl::true_ // is_nothrow_move_constructible
1789             , B // has_fallback_type
1790             ) const
1791         {
1792             // Attempt to make a temporary copy (so as to move it below)...
1793             RhsT temp(rhs_content);
1794 
1795             // ...and upon success destroy lhs's content...
1796             lhs_.destroy_content(); // nothrow
1797 
1798             // ...move the temporary copy into lhs's storage...
1799             new(lhs_.storage_.address())
1800                 RhsT( detail::variant::move(temp) ); // nothrow
1801 
1802             // ...and indicate new content type:
1803             lhs_.indicate_which(rhs_which_); // nothrow
1804         }
1805 
1806         void construct_fallback() const BOOST_NOEXCEPT {
1807             // In case of failure, default-construct fallback type in lhs's storage...
1808             new (lhs_.storage_.address())
1809                 fallback_type_; // nothrow
1810 
1811             // ...indicate construction of fallback type...
1812             lhs_.indicate_which(
1813                   BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value
1814                 ); // nothrow
1815         }
1816 
1817         template <typename RhsT>
1818         void assign_impl(
1819               const RhsT& rhs_content
1820             , mpl::false_ // has_nothrow_copy
1821             , mpl::false_ // is_nothrow_move_constructible
1822             , mpl::true_ // has_fallback_type
1823             ) const
1824         {
1825             // Destroy lhs's content...
1826             lhs_.destroy_content(); // nothrow
1827 
1828             BOOST_TRY
1829             {
1830                 // ...and attempt to copy rhs's content into lhs's storage:
1831                 new(lhs_.storage_.address())
1832                     RhsT( rhs_content );
1833             }
1834             BOOST_CATCH (...)
1835             {
1836                 construct_fallback();
1837 
1838                 // ...and rethrow:
1839                 BOOST_RETHROW;
1840             }
1841             BOOST_CATCH_END
1842 
1843             // In the event of success, indicate new content type:
1844             lhs_.indicate_which(rhs_which_); // nothrow
1845         }
1846 
1847         template <typename RhsT>
1848         void assign_impl(
1849               const RhsT& rhs_content
1850             , mpl::false_ // has_nothrow_copy
1851             , mpl::false_ // is_nothrow_move_constructible
1852             , mpl::false_ // has_fallback_type
1853             ) const
1854         {
1855             detail::variant::backup_assigner<wknd_self_t>
1856                 visitor(lhs_, rhs_which_, rhs_content);
1857             lhs_.internal_apply_visitor(visitor);
1858         }
1859 
1860     public: // internal visitor interfaces
1861 
1862         template <typename RhsT>
1863         void internal_visit(const RhsT& rhs_content, int) const
1864         {
1865             typedef typename has_nothrow_copy<RhsT>::type
1866                 nothrow_copy;
1867             typedef typename mpl::or_< // reduces compile-time
1868                   nothrow_copy
1869                 , is_nothrow_move_constructible<RhsT>
1870                 >::type nothrow_move_constructor;
1871 
1872             assign_impl(
1873                   rhs_content
1874                 , nothrow_copy()
1875                 , nothrow_move_constructor()
1876                 , has_fallback_type_()
1877                 );
1878         }
1879 
1880 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
1881     private:
1882         // silence MSVC warning C4512: assignment operator could not be generated
1883         assigner& operator= (assigner const&);
1884 #endif
1885     };
1886 
1887     friend class assigner;
1888 
1889     // class move_assigner
1890     //
1891     // Internal visitor that "move assigns" the visited value to the given variant
1892     // by appropriate destruction and move-construction.
1893     //
1894 
1895     class move_assigner
1896         : public assigner
1897     {
1898     public: // structors
1899 
1900         move_assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
1901             : assigner(lhs, rhs_which)
1902         {
1903         }
1904 
1905     private: // helpers, for internal visitor interface (below)
1906 
1907         template <typename RhsT, typename B2>
1908         void assign_impl(
1909               RhsT& rhs_content
1910             , mpl::true_ // has_nothrow_copy
1911             , mpl::false_ // is_nothrow_move_constructible
1912             , B2 // has_fallback_type
1913             ) const BOOST_NOEXCEPT
1914         {
1915             assigner::assign_impl(rhs_content, mpl::true_(), mpl::false_(), B2());
1916         }
1917 
1918         template <typename RhsT, typename B, typename B2>
1919         void assign_impl(
1920               RhsT& rhs_content
1921             , B // has_nothrow_copy
1922             , mpl::true_ // is_nothrow_move_constructible
1923             , B2 // has_fallback_type
1924             ) const BOOST_NOEXCEPT
1925         {
1926             // ...destroy lhs's content...
1927             assigner::lhs_.destroy_content(); // nothrow
1928 
1929             // ...move the rhs_content into lhs's storage...
1930             new(assigner::lhs_.storage_.address())
1931                 RhsT( detail::variant::move(rhs_content) ); // nothrow
1932 
1933             // ...and indicate new content type:
1934             assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
1935         }
1936 
1937         template <typename RhsT>
1938         void assign_impl(
1939               RhsT& rhs_content
1940             , mpl::false_ // has_nothrow_copy
1941             , mpl::false_ // is_nothrow_move_constructible
1942             , mpl::true_ // has_fallback_type
1943             ) const
1944         {
1945             // Destroy lhs's content...
1946             assigner::lhs_.destroy_content(); // nothrow
1947 
1948             BOOST_TRY
1949             {
1950                 // ...and attempt to copy rhs's content into lhs's storage:
1951                 new(assigner::lhs_.storage_.address())
1952                     RhsT( detail::variant::move(rhs_content) );
1953             }
1954             BOOST_CATCH (...)
1955             {
1956                 assigner::construct_fallback();
1957 
1958                 // ...and rethrow:
1959                 BOOST_RETHROW;
1960             }
1961             BOOST_CATCH_END
1962 
1963             // In the event of success, indicate new content type:
1964             assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
1965         }
1966 
1967         template <typename RhsT>
1968         void assign_impl(
1969               RhsT& rhs_content
1970             , mpl::false_ // has_nothrow_copy
1971             , mpl::false_ // is_nothrow_move_constructible
1972             , mpl::false_ // has_fallback_type
1973             ) const
1974         {
1975             assigner::assign_impl(rhs_content, mpl::false_(), mpl::false_(), mpl::false_());
1976         }
1977 
1978     public: // internal visitor interfaces
1979 
1980         template <typename RhsT>
1981         void internal_visit(RhsT& rhs_content, int) const
1982         {
1983             typedef typename is_nothrow_move_constructible<RhsT>::type
1984                 nothrow_move_constructor;
1985             typedef typename mpl::or_< // reduces compile-time
1986                   nothrow_move_constructor
1987                 , has_nothrow_copy<RhsT>
1988                 >::type nothrow_copy;
1989 
1990             assign_impl(
1991                   rhs_content
1992                 , nothrow_copy()
1993                 , nothrow_move_constructor()
1994                 , has_fallback_type_()
1995                 );
1996         }
1997 
1998 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
1999     private:
2000         // silence MSVC warning C4512: assignment operator could not be generated
2001         move_assigner& operator= (move_assigner const&);
2002 #endif
2003     };
2004 
2005     friend class move_assigner;
2006 
2007     void variant_assign(const variant& rhs)
2008     {
2009         // If the contained types are EXACTLY the same...
2010         if (which_ == rhs.which_)
2011         {
2012             // ...then assign rhs's storage to lhs's content:
2013             detail::variant::assign_storage visitor(rhs.storage_.address());
2014             this->internal_apply_visitor(visitor);
2015         }
2016         else
2017         {
2018             // Otherwise, perform general (copy-based) variant assignment:
2019             assigner visitor(*this, rhs.which());
2020             rhs.internal_apply_visitor(visitor);
2021         }
2022     }
2023 
2024     void variant_assign(variant&& rhs)
2025     {
2026         // If the contained types are EXACTLY the same...
2027         if (which_ == rhs.which_)
2028         {
2029             // ...then move rhs's storage to lhs's content:
2030             detail::variant::move_storage visitor(rhs.storage_.address());
2031             this->internal_apply_visitor(visitor);
2032         }
2033         else
2034         {
2035             // Otherwise, perform general (move-based) variant assignment:
2036             move_assigner visitor(*this, rhs.which());
2037             rhs.internal_apply_visitor(visitor);
2038         }
2039     }
2040 
2041 private: // helpers, for modifiers (below)
2042 
2043     template <typename T>
2044     void assign(const T& rhs)
2045     {
2046         // If direct T-to-T assignment is not possible...
2047         detail::variant::direct_assigner<T> direct_assign(rhs);
2048         if (this->apply_visitor(direct_assign) == false)
2049         {
2050             // ...then convert rhs to variant and assign:
2051             //
2052             // While potentially inefficient, the following construction of a
2053             // variant allows T as any type convertible to one of the bounded
2054             // types without excessive code redundancy.
2055             //
2056             variant temp(rhs);
2057             variant_assign( detail::variant::move(temp) );
2058         }
2059     }
2060 
2061     template <typename T>
2062     void move_assign(T&& rhs)
2063     {
2064         // If direct T-to-T move assignment is not possible...
2065         detail::variant::direct_mover<T> direct_move(rhs);
2066         if (this->apply_visitor(direct_move) == false)
2067         {
2068             // ...then convert rhs to variant and assign:
2069             //
2070             // While potentially inefficient, the following construction of a
2071             // variant allows T as any type convertible to one of the bounded
2072             // types without excessive code redundancy.
2073             //
2074             variant temp( detail::variant::move(rhs) );
2075             variant_assign( detail::variant::move(temp) );
2076         }
2077     }
2078 
2079 public: // modifiers
2080 
2081 #if !BOOST_WORKAROUND(BOOST_CLANG_VERSION, BOOST_TESTED_AT(150000)) || BOOST_CXX_VERSION <= 202002L
2082     template <class T>
2083     typename boost::enable_if<
2084         boost::mpl::and_<
2085             boost::is_rvalue_reference<T&&>,
2086             mpl::not_< boost::is_const<T> >,
2087             boost::detail::variant::is_variant_constructible_from<T&&, internal_types>
2088         >,
2089         variant&
2090     >::type operator=(T&& rhs)
2091     {
2092         move_assign( detail::variant::move(rhs) );
2093         return *this;
2094     }
2095 #endif
2096 
2097     template <typename T>
2098     typename boost::enable_if<
2099         mpl::or_<
2100             boost::is_same<T, variant>,
2101             boost::detail::variant::is_variant_constructible_from<const T&, internal_types>
2102         >,
2103         variant&
2104     >::type operator=(const T& rhs)
2105     {
2106         assign(rhs);
2107         return *this;
2108     }
2109 
2110     // [MSVC6 requires copy assign appear after templated operator=]
2111     variant& operator=(const variant& rhs)
2112     {
2113         variant_assign(rhs);
2114         return *this;
2115     }
2116 
2117     variant& operator=(variant&& rhs)
2118 #if !defined(__GNUC__) || (__GNUC__ != 4) || (__GNUC_MINOR__ > 6) || defined(__clang__)
2119         BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value && variant_move_noexcept_assignable::type::value)
2120 #endif
2121     {
2122         variant_assign( detail::variant::move(rhs) );
2123         return *this;
2124     }
2125 
2126     void swap(variant& rhs)
2127     {
2128         // If the contained types are the same...
2129         if (which() == rhs.which())
2130         {
2131             // ...then swap the values directly:
2132             detail::variant::swap_with<variant> visitor(rhs);
2133             this->apply_visitor(visitor);
2134         }
2135         else
2136         {
2137             // ...otherwise, perform general variant swap:
2138             variant tmp( detail::variant::move(rhs) );
2139             rhs = detail::variant::move(*this);
2140             *this = detail::variant::move(tmp);
2141         }
2142     }
2143 
2144 public: // queries
2145 
2146     //
2147     // NOTE: member which() defined above.
2148     //
2149 
2150     bool empty() const BOOST_NOEXCEPT
2151     {
2152         return false;
2153     }
2154 
2155     const boost::typeindex::type_info& type() const
2156     {
2157         detail::variant::reflect visitor;
2158         return this->apply_visitor(visitor);
2159     }
2160 
2161 public: // prevent comparison with foreign types
2162 
2163     template <typename U>
2164     void operator==(const U&) const
2165     {
2166         BOOST_STATIC_ASSERT( false && sizeof(U) );
2167     }
2168 
2169     template <typename U>
2170     void operator<(const U&) const
2171     {
2172         BOOST_STATIC_ASSERT( false && sizeof(U) );
2173     }
2174 
2175     template <typename U>
2176     void operator!=(const U&) const
2177     {
2178         BOOST_STATIC_ASSERT( false && sizeof(U) );
2179     }
2180 
2181     template <typename U>
2182     void operator>(const U&) const
2183     {
2184         BOOST_STATIC_ASSERT( false && sizeof(U) );
2185     }
2186 
2187     template <typename U>
2188     void operator<=(const U&) const
2189     {
2190         BOOST_STATIC_ASSERT( false && sizeof(U) );
2191     }
2192 
2193     template <typename U>
2194     void operator>=(const U&) const
2195     {
2196         BOOST_STATIC_ASSERT( false && sizeof(U) );
2197     }
2198 
2199 public: // comparison operators
2200 
2201     // [MSVC6 requires these operators appear after template operators]
2202 
2203     bool operator==(const variant& rhs) const
2204     {
2205         if (this->which() != rhs.which())
2206             return false;
2207 
2208         detail::variant::comparer<
2209               variant, detail::variant::equal_comp
2210             > visitor(*this);
2211         return rhs.apply_visitor(visitor);
2212     }
2213 
2214     bool operator<(const variant& rhs) const
2215     {
2216         //
2217         // Dirk Schreib suggested this collating order.
2218         //
2219 
2220         if (this->which() != rhs.which())
2221             return this->which() < rhs.which();
2222 
2223         detail::variant::comparer<
2224               variant, detail::variant::less_comp
2225             > visitor(*this);
2226         return rhs.apply_visitor(visitor);
2227     }
2228 
2229     ///////////////////////////////////////////////////////////////////////////////
2230     // comparison operators != > <= >=
2231     inline bool operator!=(const variant& rhs) const
2232     {
2233         return !(*this == rhs);
2234     }
2235 
2236     inline bool operator>(const variant& rhs) const
2237     {
2238         return rhs < *this;
2239     }
2240 
2241     inline bool operator<=(const variant& rhs) const
2242     {
2243         return !(*this > rhs);
2244     }
2245 
2246     inline bool operator>=(const variant& rhs) const
2247     {
2248         return !(*this < rhs);
2249     }
2250 
2251 // helpers, for visitation support (below) -- private when possible
2252 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2253 
2254     template < BOOST_VARIANT_ENUM_PARAMS(typename U) >
2255     friend class variant;
2256 
2257 private:
2258 
2259 #else// defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2260 
2261 public:
2262 
2263 #endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
2264 
2265     template <typename Visitor, typename VoidPtrCV>
2266     BOOST_FORCEINLINE static typename Visitor::result_type
2267     internal_apply_visitor_impl(
2268           int internal_which
2269         , int logical_which
2270         , Visitor& visitor
2271         , VoidPtrCV storage
2272         )
2273     {
2274         typedef mpl::int_<0> first_which;
2275         typedef typename mpl::begin<internal_types>::type first_it;
2276         typedef typename mpl::end<internal_types>::type last_it;
2277 
2278         typedef detail::variant::visitation_impl_step<
2279               first_it, last_it
2280             > first_step;
2281 
2282         return detail::variant::visitation_impl(
2283               internal_which, logical_which
2284             , visitor, storage, mpl::false_()
2285             , never_uses_backup_flag()
2286             , static_cast<first_which*>(0), static_cast<first_step*>(0)
2287             );
2288     }
2289 
2290     template <typename Visitor>
2291     BOOST_FORCEINLINE typename Visitor::result_type
2292     internal_apply_visitor(Visitor& visitor)
2293     {
2294         return internal_apply_visitor_impl(
2295               which_, which(), visitor, storage_.address()
2296             );
2297     }
2298 
2299     template <typename Visitor>
2300     BOOST_FORCEINLINE typename Visitor::result_type
2301     internal_apply_visitor(Visitor& visitor) const
2302     {
2303         return internal_apply_visitor_impl(
2304               which_, which(), visitor, storage_.address()
2305             );
2306     }
2307 
2308 public: // visitation support
2309 
2310     template <typename Visitor>
2311     typename Visitor::result_type
2312     apply_visitor(Visitor& visitor) &&
2313     {
2314         detail::variant::invoke_visitor<Visitor, true> invoker(visitor);
2315         return this->internal_apply_visitor(invoker);
2316     }
2317 
2318     template <typename Visitor>
2319     typename Visitor::result_type
2320     apply_visitor(Visitor& visitor) const&&
2321     {
2322         detail::variant::invoke_visitor<Visitor, true> invoker(visitor);
2323         return this->internal_apply_visitor(invoker);
2324     }
2325 
2326     template <typename Visitor>
2327     typename Visitor::result_type
2328     apply_visitor(Visitor& visitor) &
2329     {
2330         detail::variant::invoke_visitor<Visitor, false> invoker(visitor);
2331         return this->internal_apply_visitor(invoker);
2332     }
2333 
2334     template <typename Visitor>
2335     typename Visitor::result_type
2336     apply_visitor(Visitor& visitor) const &
2337     {
2338         detail::variant::invoke_visitor<Visitor, false> invoker(visitor);
2339         return this->internal_apply_visitor(invoker);
2340     }
2341 
2342 }; // class variant
2343 
2344 ///////////////////////////////////////////////////////////////////////////////
2345 // metafunction make_variant_over
2346 //
2347 // See docs and boost/variant/variant_fwd.hpp for more information.
2348 //
2349 template <typename Types>
2350 struct make_variant_over
2351 {
2352 private: // precondition assertions
2353 
2354     BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value ));
2355     typedef typename boost::mpl::insert_range<
2356       boost::mpl::list<>
2357     , boost::mpl::end< boost::mpl::list<> >::type
2358     , Types
2359     >::type copied_sequence_t;
2360 
2361 public: // metafunction result
2362 
2363     typedef variant<
2364           detail::variant::over_sequence<copied_sequence_t>
2365         > type;
2366 
2367 };
2368 
2369 ///////////////////////////////////////////////////////////////////////////////
2370 // function template swap
2371 //
2372 // Swaps two variants of the same type (i.e., identical specification).
2373 //
2374 template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
2375 inline void swap(
2376       variant< BOOST_VARIANT_ENUM_PARAMS(T) >& lhs
2377     , variant< BOOST_VARIANT_ENUM_PARAMS(T) >& rhs
2378     )
2379 {
2380     lhs.swap(rhs);
2381 }
2382 
2383 } // namespace boost
2384 
2385 // implementation additions
2386 
2387 #if !defined(BOOST_NO_IOSTREAM)
2388 #include <boost/variant/detail/variant_io.hpp>
2389 #endif // BOOST_NO_IOSTREAM
2390 
2391 #endif // BOOST_VARIANT_VARIANT_HPP