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