File indexing completed on 2025-01-18 09:53:33
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/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
0094
0095
0096
0097
0098
0099
0100
0101
0102
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
0123
0124
0125
0126 template <typename Sequence, typename F>
0127 struct max_value
0128 {
0129 private:
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:
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
0158
0159
0160
0161
0162
0163
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:
0185
0186 typedef typename mpl::end<Types>::type end_it;
0187
0188
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
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:
0210
0211
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
0226
0227
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
0243
0244
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
0260
0261
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
0322
0323
0324
0325
0326
0327 template <typename Types, typename NeverUsesBackupFlag>
0328 struct make_storage
0329 {
0330 private:
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
0353
0354
0355 typedef mpl::size_t< -1 > max_alignment;
0356
0357 #endif
0358
0359 public:
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
0369
0370
0371
0372 struct destroyer
0373 : public static_visitor<>
0374 {
0375 public:
0376
0377 template <typename T>
0378 void internal_visit(T& operand, int) const BOOST_NOEXCEPT
0379 {
0380 operand.~T();
0381
0382 #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0551)) || \
0383 BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
0384 (void)operand;
0385 #endif
0386 }
0387
0388 };
0389
0390
0391
0392
0393
0394
0395
0396
0397 template <typename T>
0398 class known_get
0399 : public static_visitor<T&>
0400 {
0401
0402 public:
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
0413 return ::boost::detail::variant::forced_return< T& >();
0414 }
0415 };
0416
0417
0418
0419
0420
0421
0422 class copy_into
0423 : public static_visitor<>
0424 {
0425 private:
0426
0427 void* storage_;
0428
0429 public:
0430
0431 explicit copy_into(void* storage) BOOST_NOEXCEPT
0432 : storage_(storage)
0433 {
0434 }
0435
0436 public:
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
0460
0461
0462
0463 class move_into
0464 : public static_visitor<>
0465 {
0466 private:
0467
0468 void* storage_;
0469
0470 public:
0471
0472 explicit move_into(void* storage) BOOST_NOEXCEPT
0473 : storage_(storage)
0474 {
0475 }
0476
0477 public:
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
0494
0495
0496
0497
0498 struct assign_storage
0499 : public static_visitor<>
0500 {
0501 private:
0502
0503 const void* rhs_storage_;
0504
0505 public:
0506
0507 explicit assign_storage(const void* rhs_storage) BOOST_NOEXCEPT
0508 : rhs_storage_(rhs_storage)
0509 {
0510 }
0511
0512 public:
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
0532
0533
0534
0535
0536
0537
0538 lhs_content = *static_cast< const T* >(rhs_storage_);
0539 }
0540
0541 };
0542
0543
0544
0545
0546
0547
0548
0549 struct move_storage
0550 : public static_visitor<>
0551 {
0552 private:
0553
0554 void* rhs_storage_;
0555
0556 public:
0557
0558 explicit move_storage(void* rhs_storage) BOOST_NOEXCEPT
0559 : rhs_storage_(rhs_storage)
0560 {
0561 }
0562
0563 public:
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
0583
0584
0585
0586
0587
0588
0589 lhs_content = ::boost::detail::variant::move(*static_cast<T* >(rhs_storage_));
0590 }
0591
0592 };
0593
0594
0595
0596
0597
0598
0599
0600
0601 template <typename T>
0602 class direct_assigner
0603 : public static_visitor<bool>
0604 {
0605 private:
0606
0607 const T& rhs_;
0608
0609 public:
0610
0611 explicit direct_assigner(const T& rhs) BOOST_NOEXCEPT
0612 : rhs_(rhs)
0613 {
0614 }
0615
0616 public:
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
0633 direct_assigner& operator= (direct_assigner const&);
0634 #endif
0635 };
0636
0637
0638
0639
0640
0641
0642
0643
0644 template <typename T>
0645 class direct_mover
0646 : public static_visitor<bool>
0647 {
0648 private:
0649
0650 T& rhs_;
0651
0652 public:
0653
0654 explicit direct_mover(T& rhs) BOOST_NOEXCEPT
0655 : rhs_(rhs)
0656 {
0657 }
0658
0659 public:
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
0676 direct_mover& operator= (direct_mover const&);
0677 #endif
0678 };
0679
0680
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690 template <typename Variant>
0691 class backup_assigner
0692 : public static_visitor<>
0693 {
0694 private:
0695
0696 Variant& lhs_;
0697 int rhs_which_;
0698 const void* rhs_content_;
0699 void (*copy_rhs_content_)(void*, const void*);
0700
0701 public:
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:
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_
0724 , long
0725 )
0726 {
0727
0728 backup_holder<LhsT> backup_lhs_content(0);
0729 backup_lhs_content.swap(lhs_content);
0730
0731
0732 lhs_content.~backup_holder<LhsT>();
0733
0734 BOOST_TRY
0735 {
0736
0737 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
0738 }
0739 BOOST_CATCH (...)
0740 {
0741
0742 new(lhs_.storage_.address())
0743 backup_holder<LhsT>( 0 );
0744
0745 static_cast<backup_holder<LhsT>* >(lhs_.storage_.address())
0746 ->swap(backup_lhs_content);
0747
0748
0749 BOOST_RETHROW;
0750 }
0751 BOOST_CATCH_END
0752
0753
0754 lhs_.indicate_which(rhs_which_);
0755 }
0756
0757 template <typename LhsT>
0758 void backup_assign_impl(
0759 LhsT& lhs_content
0760 , mpl::true_
0761 , int
0762 )
0763 {
0764
0765 LhsT backup_lhs_content(
0766 ::boost::detail::variant::move(lhs_content)
0767 );
0768
0769
0770 lhs_content.~LhsT();
0771
0772 BOOST_TRY
0773 {
0774
0775 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
0776 }
0777 BOOST_CATCH (...)
0778 {
0779
0780 new(lhs_.storage_.address())
0781 LhsT(
0782 ::boost::detail::variant::move(backup_lhs_content)
0783 );
0784
0785
0786 BOOST_RETHROW;
0787 }
0788 BOOST_CATCH_END
0789
0790
0791 lhs_.indicate_which(rhs_which_);
0792 }
0793
0794 template <typename LhsT>
0795 void backup_assign_impl(
0796 LhsT& lhs_content
0797 , mpl::false_
0798 , int
0799 )
0800 {
0801
0802 LhsT* backup_lhs_ptr = new LhsT(lhs_content);
0803
0804
0805 lhs_content.~LhsT();
0806
0807 BOOST_TRY
0808 {
0809
0810 copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
0811 }
0812 BOOST_CATCH (...)
0813 {
0814
0815 new(lhs_.storage_.address())
0816 backup_holder<LhsT>( backup_lhs_ptr );
0817
0818
0819 lhs_.indicate_backup_which( lhs_.which() );
0820
0821
0822 BOOST_RETHROW;
0823 }
0824 BOOST_CATCH_END
0825
0826
0827 lhs_.indicate_which(rhs_which_);
0828
0829
0830 delete backup_lhs_ptr;
0831 }
0832
0833 public:
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
0847 backup_assigner& operator= (backup_assigner const&);
0848 #endif
0849 };
0850
0851
0852
0853
0854
0855
0856
0857
0858 template <typename Variant>
0859 struct swap_with
0860 : public static_visitor<>
0861 {
0862 private:
0863
0864 Variant& toswap_;
0865
0866 public:
0867
0868 explicit swap_with(Variant& toswap) BOOST_NOEXCEPT
0869 : toswap_(toswap)
0870 {
0871 }
0872
0873 public:
0874
0875 template <typename T>
0876 void operator()(T& operand) const
0877 {
0878
0879 known_get<T> getter;
0880 T& other = toswap_.apply_visitor(getter);
0881
0882
0883 ::boost::detail::variant::move_swap( operand, other );
0884 }
0885
0886 private:
0887 swap_with& operator=(const swap_with&);
0888
0889 };
0890
0891
0892
0893
0894
0895
0896
0897 class reflect
0898 : public static_visitor<const boost::typeindex::type_info&>
0899 {
0900 public:
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
0912
0913
0914
0915
0916
0917
0918 template <typename Variant, typename Comp>
0919 class comparer
0920 : public static_visitor<bool>
0921 {
0922 private:
0923
0924 const Variant& lhs_;
0925
0926 public:
0927
0928 explicit comparer(const Variant& lhs) BOOST_NOEXCEPT
0929 : lhs_(lhs)
0930 {
0931 }
0932
0933 public:
0934
0935 template <typename T>
0936 bool operator()(T& rhs_content) const
0937 {
0938
0939 known_get<T> getter;
0940 const T& lhs_content = lhs_.apply_visitor(getter);
0941
0942
0943 return Comp()(lhs_content, rhs_content);
0944 }
0945
0946 private:
0947 comparer& operator=(const comparer&);
0948
0949 };
0950
0951
0952
0953
0954
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
0967
0968
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
0981
0982
0983
0984
0985
0986 template <typename Visitor, bool MoveSemantics>
0987 class invoke_visitor
0988 {
0989 private:
0990
0991 Visitor& visitor_;
0992
0993 public:
0994
0995 typedef typename Visitor::result_type
0996 result_type;
0997
0998 public:
0999
1000 explicit invoke_visitor(Visitor& visitor) BOOST_NOEXCEPT
1001 : visitor_(visitor)
1002 {
1003 }
1004
1005 public:
1006
1007
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
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:
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
1062 invoke_visitor& operator= (invoke_visitor const&);
1063 #endif
1064 };
1065
1066 }}
1067
1068
1069
1070
1071
1072
1073 template <
1074 typename T0_
1075 , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)
1076 >
1077 class variant
1078 {
1079 private:
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:
1102
1103 typedef typename mpl::eval_if<
1104 is_sequence_based_
1105 , unwrapped_T0_
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:
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;
1127
1128 typedef typename mpl::transform<
1129 recursive_enabled_types
1130 , unwrap_recursive<mpl::_1>
1131 >::type types;
1132
1133 private:
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
1145
1146 private:
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:
1184
1185 typedef typename detail::variant::make_variant_list<
1186 BOOST_VARIANT_ENUM_PARAMS(public_T)
1187 >::type types;
1188
1189 private:
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:
1206
1207 typedef typename detail::variant::make_variant_list<
1208 BOOST_VARIANT_ENUM_PARAMS(internal_T)
1209 >::type internal_types;
1210
1211 private:
1212
1213
1214
1215
1216 BOOST_MPL_ASSERT_NOT(( is_sequence_based_ ));
1217
1218 #endif
1219
1220 private:
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:
1254
1255
1256
1257
1258
1259
1260
1261
1262 #if !defined(BOOST_VARIANT_MINIMIZE_SIZE)
1263
1264 typedef int which_t;
1265
1266 #else
1267
1268
1269
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
1281
1282
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:
1303
1304 bool using_backup() const BOOST_NOEXCEPT
1305 {
1306 return which_ < 0;
1307 }
1308
1309 public:
1310
1311 int which() const BOOST_NOEXCEPT
1312 {
1313
1314 if (using_backup())
1315
1316 return -(which_ + 1);
1317
1318
1319 return which_;
1320 }
1321
1322 private:
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:
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
1352 #pragma warning( disable : 4345 )
1353 #endif
1354
1355
1356
1357
1358
1359 new( storage_.address() ) internal_T0();
1360 indicate_which(0);
1361 #ifdef _MSC_VER
1362 #pragma warning( pop )
1363 #endif
1364 }
1365
1366 private:
1367
1368 class convert_copy_into
1369 : public static_visitor<int>
1370 {
1371 private:
1372
1373 void* storage_;
1374
1375 public:
1376
1377 explicit convert_copy_into(void* storage) BOOST_NOEXCEPT
1378 : storage_(storage)
1379 {
1380 }
1381
1382 public:
1383
1384 template <typename T>
1385 int internal_visit(T& operand, int) const
1386 {
1387
1388
1389
1390
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:
1447
1448 void* storage_;
1449
1450 public:
1451
1452 explicit convert_move_into(void* storage) BOOST_NOEXCEPT
1453 : storage_(storage)
1454 {
1455 }
1456
1457 public:
1458
1459 template <typename T>
1460 int internal_visit(T& operand, int) const
1461 {
1462
1463
1464
1465
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:
1510
1511 template <typename T>
1512 void convert_construct(
1513 T& operand
1514 , int
1515 , mpl::false_ = mpl::false_()
1516 )
1517 {
1518
1519
1520
1521
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_()
1536 )
1537 {
1538
1539
1540
1541
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_
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_
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
1581
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
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
1608
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
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:
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:
1714
1715
1716 variant(const variant& operand)
1717 {
1718
1719 detail::variant::copy_into visitor( storage_.address() );
1720 operand.internal_apply_visitor(visitor);
1721
1722
1723 indicate_which(operand.which());
1724 }
1725
1726 variant(variant&& operand) BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value)
1727 {
1728
1729 detail::variant::move_into visitor( storage_.address() );
1730 operand.internal_apply_visitor(visitor);
1731
1732
1733 indicate_which(operand.which());
1734 }
1735
1736 private:
1737
1738 template <typename Variant>
1739 friend class detail::variant::backup_assigner;
1740
1741
1742
1743
1744
1745
1746
1747 class assigner
1748 : public static_visitor<>
1749 {
1750 protected:
1751
1752 variant& lhs_;
1753 const int rhs_which_;
1754
1755 public:
1756
1757 assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
1758 : lhs_(lhs)
1759 , rhs_which_(rhs_which)
1760 {
1761 }
1762
1763 protected:
1764
1765 template <typename RhsT, typename B1, typename B2>
1766 void assign_impl(
1767 const RhsT& rhs_content
1768 , mpl::true_
1769 , B1
1770 , B2
1771 ) const BOOST_NOEXCEPT
1772 {
1773
1774 lhs_.destroy_content();
1775
1776
1777 new(lhs_.storage_.address())
1778 RhsT( rhs_content );
1779
1780
1781 lhs_.indicate_which(rhs_which_);
1782 }
1783
1784 template <typename RhsT, typename B>
1785 void assign_impl(
1786 const RhsT& rhs_content
1787 , mpl::false_
1788 , mpl::true_
1789 , B
1790 ) const
1791 {
1792
1793 RhsT temp(rhs_content);
1794
1795
1796 lhs_.destroy_content();
1797
1798
1799 new(lhs_.storage_.address())
1800 RhsT( detail::variant::move(temp) );
1801
1802
1803 lhs_.indicate_which(rhs_which_);
1804 }
1805
1806 void construct_fallback() const BOOST_NOEXCEPT {
1807
1808 new (lhs_.storage_.address())
1809 fallback_type_;
1810
1811
1812 lhs_.indicate_which(
1813 BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value
1814 );
1815 }
1816
1817 template <typename RhsT>
1818 void assign_impl(
1819 const RhsT& rhs_content
1820 , mpl::false_
1821 , mpl::false_
1822 , mpl::true_
1823 ) const
1824 {
1825
1826 lhs_.destroy_content();
1827
1828 BOOST_TRY
1829 {
1830
1831 new(lhs_.storage_.address())
1832 RhsT( rhs_content );
1833 }
1834 BOOST_CATCH (...)
1835 {
1836 construct_fallback();
1837
1838
1839 BOOST_RETHROW;
1840 }
1841 BOOST_CATCH_END
1842
1843
1844 lhs_.indicate_which(rhs_which_);
1845 }
1846
1847 template <typename RhsT>
1848 void assign_impl(
1849 const RhsT& rhs_content
1850 , mpl::false_
1851 , mpl::false_
1852 , mpl::false_
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:
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_<
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
1883 assigner& operator= (assigner const&);
1884 #endif
1885 };
1886
1887 friend class assigner;
1888
1889
1890
1891
1892
1893
1894
1895 class move_assigner
1896 : public assigner
1897 {
1898 public:
1899
1900 move_assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
1901 : assigner(lhs, rhs_which)
1902 {
1903 }
1904
1905 private:
1906
1907 template <typename RhsT, typename B2>
1908 void assign_impl(
1909 RhsT& rhs_content
1910 , mpl::true_
1911 , mpl::false_
1912 , B2
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
1922 , mpl::true_
1923 , B2
1924 ) const BOOST_NOEXCEPT
1925 {
1926
1927 assigner::lhs_.destroy_content();
1928
1929
1930 new(assigner::lhs_.storage_.address())
1931 RhsT( detail::variant::move(rhs_content) );
1932
1933
1934 assigner::lhs_.indicate_which(assigner::rhs_which_);
1935 }
1936
1937 template <typename RhsT>
1938 void assign_impl(
1939 RhsT& rhs_content
1940 , mpl::false_
1941 , mpl::false_
1942 , mpl::true_
1943 ) const
1944 {
1945
1946 assigner::lhs_.destroy_content();
1947
1948 BOOST_TRY
1949 {
1950
1951 new(assigner::lhs_.storage_.address())
1952 RhsT( detail::variant::move(rhs_content) );
1953 }
1954 BOOST_CATCH (...)
1955 {
1956 assigner::construct_fallback();
1957
1958
1959 BOOST_RETHROW;
1960 }
1961 BOOST_CATCH_END
1962
1963
1964 assigner::lhs_.indicate_which(assigner::rhs_which_);
1965 }
1966
1967 template <typename RhsT>
1968 void assign_impl(
1969 RhsT& rhs_content
1970 , mpl::false_
1971 , mpl::false_
1972 , mpl::false_
1973 ) const
1974 {
1975 assigner::assign_impl(rhs_content, mpl::false_(), mpl::false_(), mpl::false_());
1976 }
1977
1978 public:
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_<
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
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
2010 if (which_ == rhs.which_)
2011 {
2012
2013 detail::variant::assign_storage visitor(rhs.storage_.address());
2014 this->internal_apply_visitor(visitor);
2015 }
2016 else
2017 {
2018
2019 assigner visitor(*this, rhs.which());
2020 rhs.internal_apply_visitor(visitor);
2021 }
2022 }
2023
2024 void variant_assign(variant&& rhs)
2025 {
2026
2027 if (which_ == rhs.which_)
2028 {
2029
2030 detail::variant::move_storage visitor(rhs.storage_.address());
2031 this->internal_apply_visitor(visitor);
2032 }
2033 else
2034 {
2035
2036 move_assigner visitor(*this, rhs.which());
2037 rhs.internal_apply_visitor(visitor);
2038 }
2039 }
2040
2041 private:
2042
2043 template <typename T>
2044 void assign(const T& rhs)
2045 {
2046
2047 detail::variant::direct_assigner<T> direct_assign(rhs);
2048 if (this->apply_visitor(direct_assign) == false)
2049 {
2050
2051
2052
2053
2054
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
2065 detail::variant::direct_mover<T> direct_move(rhs);
2066 if (this->apply_visitor(direct_move) == false)
2067 {
2068
2069
2070
2071
2072
2073
2074 variant temp( detail::variant::move(rhs) );
2075 variant_assign( detail::variant::move(temp) );
2076 }
2077 }
2078
2079 public:
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
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
2129 if (which() == rhs.which())
2130 {
2131
2132 detail::variant::swap_with<variant> visitor(rhs);
2133 this->apply_visitor(visitor);
2134 }
2135 else
2136 {
2137
2138 variant tmp( detail::variant::move(rhs) );
2139 rhs = detail::variant::move(*this);
2140 *this = detail::variant::move(tmp);
2141 }
2142 }
2143
2144 public:
2145
2146
2147
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:
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:
2200
2201
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
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
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
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
2260
2261 public:
2262
2263 #endif
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:
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 };
2343
2344
2345
2346
2347
2348
2349 template <typename Types>
2350 struct make_variant_over
2351 {
2352 private:
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:
2362
2363 typedef variant<
2364 detail::variant::over_sequence<copied_sequence_t>
2365 > type;
2366
2367 };
2368
2369
2370
2371
2372
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 }
2384
2385
2386
2387 #if !defined(BOOST_NO_IOSTREAM)
2388 #include <boost/variant/detail/variant_io.hpp>
2389 #endif
2390
2391 #endif