File indexing completed on 2025-01-18 10:09:47
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef RANGES_V3_DETAIL_VARIANT_HPP
0014 #define RANGES_V3_DETAIL_VARIANT_HPP
0015
0016 #include <iterator>
0017 #include <memory>
0018 #include <new>
0019 #include <stdexcept>
0020 #include <tuple>
0021 #include <type_traits>
0022 #include <utility>
0023
0024 #include <meta/meta.hpp>
0025
0026 #include <concepts/concepts.hpp>
0027
0028 #include <range/v3/range_fwd.hpp>
0029
0030 #include <range/v3/functional/compose.hpp>
0031 #include <range/v3/functional/identity.hpp>
0032 #include <range/v3/functional/invoke.hpp>
0033 #include <range/v3/iterator/concepts.hpp>
0034 #include <range/v3/iterator/traits.hpp>
0035 #include <range/v3/utility/get.hpp>
0036
0037 #include <range/v3/detail/prologue.hpp>
0038
0039 namespace ranges
0040 {
0041 template<std::size_t I>
0042 struct emplaced_index_t;
0043
0044 template<std::size_t I>
0045 struct emplaced_index_t : meta::size_t<I>
0046 {};
0047
0048 #if RANGES_CXX_INLINE_VARIABLES < RANGES_CXX_INLINE_VARIABLES_17
0049 namespace
0050 {
0051 template<std::size_t I>
0052 constexpr auto & emplaced_index = static_const<emplaced_index_t<I>>::value;
0053 }
0054 #else
0055 template<std::size_t I>
0056 inline constexpr emplaced_index_t<I> emplaced_index{};
0057 #endif
0058
0059 struct bad_variant_access : std::logic_error
0060 {
0061 explicit bad_variant_access(std::string const & what_arg)
0062 : std::logic_error(what_arg)
0063 {}
0064 explicit bad_variant_access(char const * what_arg)
0065 : std::logic_error(what_arg)
0066 {}
0067 };
0068
0069 template<typename T, std::size_t Index>
0070 struct indexed_element
0071 {
0072 private:
0073 std::add_pointer_t<T> t_;
0074
0075 public:
0076 constexpr explicit indexed_element(T & t) noexcept
0077 : t_(std::addressof(t))
0078 {}
0079 constexpr T & get() const noexcept
0080 {
0081 return *t_;
0082 }
0083 };
0084 template<typename T, std::size_t Index>
0085 struct indexed_element<T &&, Index>
0086 {
0087 private:
0088 T * t_;
0089
0090 public:
0091 constexpr explicit indexed_element(T && t) noexcept
0092 : t_(std::addressof(t))
0093 {}
0094 constexpr T && get() const noexcept
0095 {
0096 return static_cast<T &&>(*t_);
0097 }
0098 };
0099 template<std::size_t Index>
0100 struct indexed_element<void, Index>
0101 {
0102 void get() const noexcept
0103 {}
0104 };
0105
0106
0107 namespace detail
0108 {
0109 struct indexed_element_fn;
0110
0111 template(typename I, typename S, typename O)(
0112 requires (!sized_sentinel_for<S, I>))
0113 O uninitialized_copy(I first, S last, O out)
0114 {
0115 for(; first != last; ++first, ++out)
0116 ::new((void *)std::addressof(*out)) iter_value_t<O>(*first);
0117 return out;
0118 }
0119
0120 template(typename I, typename S, typename O)(
0121 requires sized_sentinel_for<S, I>)
0122 O uninitialized_copy(I first, S last, O out)
0123 {
0124 return std::uninitialized_copy_n(first, (last - first), out);
0125 }
0126
0127 template<typename I, typename O>
0128 O uninitialized_copy(I first, I last, O out)
0129 {
0130 return std::uninitialized_copy(first, last, out);
0131 }
0132
0133 template<typename T, typename Index>
0134 struct indexed_datum
0135 {
0136 private:
0137 template<typename, typename>
0138 friend struct indexed_datum;
0139 T datum_;
0140
0141 public:
0142 CPP_member
0143 constexpr CPP_ctor(indexed_datum)()(
0144 noexcept(std::is_nothrow_default_constructible<T>::value)
0145 requires default_constructible<T>)
0146 : datum_{}
0147 {}
0148 template(typename... Ts)(
0149 requires constructible_from<T, Ts...> AND (sizeof...(Ts) != 0))
0150 constexpr indexed_datum(Ts &&... ts) noexcept(
0151 std::is_nothrow_constructible<T, Ts...>::value)
0152 : datum_(static_cast<Ts &&>(ts)...)
0153 {}
0154 template(typename U)(
0155 requires (!same_as<T, U>) AND convertible_to<U, T>)
0156 constexpr indexed_datum(indexed_datum<U, Index> that)
0157 noexcept(std::is_nothrow_constructible<T, U>::value)
0158 : datum_(std::move(that.datum_))
0159 {}
0160 constexpr auto ref() noexcept
0161 {
0162 return indexed_element<T, Index::value>{datum_};
0163 }
0164 constexpr auto ref() const noexcept
0165 {
0166 return indexed_element<T const, Index::value>{datum_};
0167 }
0168 constexpr T & get() noexcept
0169 {
0170 return datum_;
0171 }
0172 constexpr T const & get() const noexcept
0173 {
0174 return datum_;
0175 }
0176 };
0177
0178 template<typename T, std::size_t N, typename Index>
0179 struct indexed_datum<T[N], Index>;
0180
0181 template<typename T, typename Index>
0182 struct indexed_datum<T &, Index>
0183 {
0184 private:
0185 template<typename, typename>
0186 friend struct indexed_datum;
0187 T * t_;
0188
0189 public:
0190 constexpr indexed_datum(T & t) noexcept
0191 : t_(std::addressof(t))
0192 {}
0193 constexpr T & get() const noexcept
0194 {
0195 return *t_;
0196 }
0197 constexpr auto ref() const noexcept
0198 {
0199 return indexed_element<T &, Index::value>{*t_};
0200 }
0201 };
0202 template<typename T, typename Index>
0203 struct indexed_datum<T &&, Index>
0204 {
0205 private:
0206 template<typename, typename>
0207 friend struct indexed_datum;
0208 T * t_;
0209
0210 public:
0211 constexpr indexed_datum(T && t) noexcept
0212 : t_(std::addressof(t))
0213 {}
0214 constexpr T && get() const noexcept
0215 {
0216 return static_cast<T &&>(*t_);
0217 }
0218 constexpr auto ref() const noexcept
0219 {
0220 return indexed_element<T &&, Index::value>{static_cast<T &&>(*t_)};
0221 }
0222 };
0223 template<typename Index>
0224 struct indexed_datum<void, Index>
0225 {
0226 void get() const noexcept
0227 {}
0228 constexpr indexed_element<void, Index::value> ref() const noexcept
0229 {
0230 return {};
0231 }
0232 };
0233
0234 template<std::size_t Index, typename... Ts>
0235 using variant_datum_t =
0236 detail::indexed_datum<meta::at_c<meta::list<Ts...>, Index>,
0237 meta::size_t<Index>>;
0238
0239 using variant_nil = indexed_datum<void, meta::npos>;
0240
0241 template<typename Ts,
0242 bool Trivial = meta::apply<
0243 meta::quote<meta::and_>,
0244 meta::transform<Ts, meta::quote<std::is_trivially_destructible>>>::
0245 type::value>
0246 struct variant_data_
0247 {
0248 using type = indexed_datum<void, meta::npos>;
0249 };
0250
0251 template<typename T, typename... Ts>
0252 struct variant_data_<meta::list<T, Ts...>, true>
0253 {
0254 struct type
0255 {
0256 using head_t = T;
0257 using tail_t = meta::_t<variant_data_<meta::list<Ts...>>>;
0258 union
0259 {
0260 head_t head;
0261 tail_t tail;
0262 };
0263
0264 type() noexcept
0265 {}
0266 template<typename... Args>
0267 constexpr type(meta::size_t<0>, Args &&... args) noexcept(
0268 std::is_nothrow_constructible<head_t, Args...>::value)
0269 : head{((Args &&) args)...}
0270 {}
0271 template<std::size_t N, typename... Args>
0272 constexpr type(meta::size_t<N>, Args &&... args) noexcept(
0273 std::is_nothrow_constructible<tail_t, meta::size_t<N - 1>,
0274 Args...>::value)
0275 : tail{meta::size_t<N - 1>{}, ((Args &&) args)...}
0276 {}
0277 };
0278 };
0279
0280 template<typename T, typename... Ts>
0281 struct variant_data_<meta::list<T, Ts...>, false>
0282 {
0283 struct type
0284 {
0285 using head_t = T;
0286 using tail_t = meta::_t<variant_data_<meta::list<Ts...>>>;
0287 union
0288 {
0289 head_t head;
0290 tail_t tail;
0291 };
0292
0293 type() noexcept
0294 {}
0295 ~type()
0296 {}
0297 template<typename... Args>
0298 constexpr type(meta::size_t<0>, Args &&... args) noexcept(
0299 std::is_nothrow_constructible<head_t, Args...>::value)
0300 : head{((Args &&) args)...}
0301 {}
0302 template<std::size_t N, typename... Args>
0303 constexpr type(meta::size_t<N>, Args &&... args) noexcept(
0304 std::is_nothrow_constructible<tail_t, meta::size_t<N - 1>,
0305 Args...>::value)
0306 : tail{meta::size_t<N - 1>{}, ((Args &&) args)...}
0307 {}
0308 };
0309 };
0310
0311 template<typename... Ts>
0312 using variant_data = meta::_t<variant_data_<meta::transform<
0313 meta::list<Ts...>, meta::as_list<meta::make_index_sequence<sizeof...(Ts)>>,
0314 meta::quote<indexed_datum>>>>;
0315
0316 inline std::size_t variant_move_copy_(std::size_t, variant_nil, variant_nil)
0317 {
0318 return 0;
0319 }
0320 template<typename Data0, typename Data1>
0321 std::size_t variant_move_copy_(std::size_t n, Data0 & self, Data1 && that)
0322 {
0323 using Head = typename Data0::head_t;
0324 return 0 == n
0325 ? ((void)::new((void *)&self.head) Head(((Data1 &&) that).head), 0)
0326 : variant_move_copy_(n - 1, self.tail, ((Data1 &&) that).tail) + 1;
0327 }
0328 constexpr bool variant_equal_(std::size_t, variant_nil, variant_nil)
0329 {
0330 return true;
0331 }
0332 template<typename Data0, typename Data1>
0333 constexpr bool variant_equal_(std::size_t n, Data0 const & self,
0334 Data1 const & that)
0335 {
0336 return n == 0 ? self.head.get() == that.head.get()
0337 : variant_equal_(n - 1, self.tail, that.tail);
0338 }
0339 template<typename Fun, typename Proj = indexed_element_fn>
0340 constexpr int variant_visit_(std::size_t, variant_nil, Fun, Proj = {})
0341 {
0342 return (RANGES_EXPECT(false), 0);
0343 }
0344 template<typename Data, typename Fun, typename Proj = indexed_element_fn>
0345 constexpr int variant_visit_(std::size_t n, Data & self, Fun fun, Proj proj = {})
0346 {
0347 return 0 == n ? ((void)invoke(fun, invoke(proj, self.head)), 0)
0348 : detail::variant_visit_(
0349 n - 1, self.tail, detail::move(fun), detail::move(proj));
0350 }
0351
0352 struct get_datum_fn
0353 {
0354 template<typename T>
0355 decltype(auto) operator()(T && t) const noexcept
0356 {
0357 return t.get();
0358 }
0359 };
0360
0361 struct indexed_element_fn
0362 {
0363 template<typename T>
0364 decltype(auto) operator()(T && t) const noexcept
0365 {
0366 return t.ref();
0367 }
0368 };
0369
0370 struct empty_variant_tag
0371 {};
0372
0373 struct variant_core_access
0374 {
0375 template<typename... Ts>
0376 static constexpr variant_data<Ts...> & data(variant<Ts...> & var) noexcept
0377 {
0378 return var.data_();
0379 }
0380 template<typename... Ts>
0381 static constexpr variant_data<Ts...> const & data(
0382 variant<Ts...> const & var) noexcept
0383 {
0384 return var.data_();
0385 }
0386 template<typename... Ts>
0387 static constexpr variant_data<Ts...> && data(variant<Ts...> && var) noexcept
0388 {
0389 return detail::move(var.data_());
0390 }
0391 template<typename... Ts>
0392 static variant<Ts...> make_empty(meta::id<variant<Ts...>> = {}) noexcept
0393 {
0394 return variant<Ts...>{empty_variant_tag{}};
0395 }
0396 };
0397
0398 struct delete_fn
0399 {
0400 template<typename T>
0401 void operator()(T const & t) const noexcept
0402 {
0403 t.~T();
0404 }
0405 };
0406
0407 template<std::size_t N, typename... Ts>
0408 struct construct_fn
0409 {
0410 std::tuple<Ts...> args_;
0411
0412 template<typename U, std::size_t... Is>
0413 void construct_(U & u, meta::index_sequence<Is...>) noexcept(
0414 std::is_nothrow_constructible<U, Ts...>::value)
0415 {
0416 ::new((void *)std::addressof(u))
0417 U(static_cast<Ts &&>(std::get<Is>(args_))...);
0418 }
0419
0420 construct_fn(Ts &&... ts) noexcept(
0421 std::is_nothrow_constructible<std::tuple<Ts...>, Ts...>::value)
0422 : args_{static_cast<Ts &&>(ts)...}
0423 {}
0424 template<typename U, std::size_t M>
0425 [[noreturn]] meta::if_c<N != M> operator()(
0426 indexed_datum<U, meta::size_t<M>> &) noexcept
0427 {
0428 RANGES_EXPECT(false);
0429 }
0430 template<typename U>
0431 meta::if_<std::is_object<U>> operator()(
0432 indexed_datum<U, meta::size_t<N>> &
0433 u) noexcept(std::is_nothrow_constructible<U, Ts...>::value)
0434 {
0435 this->construct_(u.get(), meta::make_index_sequence<sizeof...(Ts)>{});
0436 }
0437 template<typename U>
0438 meta::if_<meta::not_<std::is_object<U>>> operator()(
0439 indexed_datum<U, meta::size_t<N>> &
0440 u) noexcept(std::is_nothrow_constructible<detail::decay_t<U>,
0441 Ts...>::value)
0442 {
0443 this->construct_(u, meta::make_index_sequence<sizeof...(Ts)>{});
0444 }
0445 };
0446
0447 template<typename T, std::size_t N>
0448 struct get_fn
0449 {
0450 T ** t_;
0451
0452 template<typename U, std::size_t M>
0453 [[noreturn]] meta::if_c<M != N> operator()(indexed_element<U, M>) const
0454 {
0455 throw bad_variant_access("bad variant access");
0456 }
0457 template<typename U>
0458 void operator()(indexed_element<U, N> t) const noexcept
0459 {
0460 *t_ = std::addressof(t.get());
0461 }
0462 template<typename U>
0463 void operator()(indexed_element<U &&, N> t) const noexcept
0464 {
0465 U && u = t.get();
0466 *t_ = std::addressof(u);
0467 }
0468 void operator()(indexed_element<void, N>) const noexcept
0469 {}
0470 };
0471
0472 template<typename Variant, std::size_t N>
0473 struct emplace_fn
0474 {
0475 Variant * var_;
0476
0477 template<typename...Ts>
0478 auto CPP_auto_fun(operator())(Ts &&...ts) (const)
0479 (
0480 return var_->template emplace<N>(static_cast<Ts &&>(ts)...)
0481 )
0482
0483 };
0484
0485 template<typename Fun, typename Variant>
0486 struct variant_visitor
0487 {
0488 Fun fun_;
0489 Variant * var_;
0490
0491
0492 template<typename U, std::size_t N>
0493 auto CPP_auto_fun(operator())(indexed_element<U, N> u)
0494 (
0495 return compose(emplace_fn<Variant, N>{var_}, fun_)(u)
0496 )
0497
0498 };
0499
0500 template<typename Variant, typename Fun>
0501 variant_visitor<Fun, Variant> make_variant_visitor(
0502 Variant & var,
0503 Fun fun) noexcept(std::is_nothrow_move_constructible<Fun>::value)
0504 {
0505 return {detail::move(fun), &var};
0506 }
0507
0508 template<typename To, typename From>
0509 struct unique_visitor;
0510
0511 template<typename... To, typename... From>
0512 struct unique_visitor<variant<To...>, variant<From...>>
0513 {
0514 variant<To...> * var_;
0515
0516 template<typename T, std::size_t N>
0517 void operator()(indexed_element<T, N> t) const
0518 {
0519 using E = meta::at_c<meta::list<From...>, N>;
0520 static_assert(RANGES_IS_SAME(T const, E const),
0521 "Is indexed_element broken?");
0522 using F = meta::find<meta::list<To...>, E>;
0523 static constexpr std::size_t M = sizeof...(To) - F::size();
0524 compose(emplace_fn<variant<To...>, M>{var_}, get_datum_fn{})(t);
0525 }
0526 };
0527
0528 template<typename T>
0529 constexpr T & variant_deref_(T * t) noexcept
0530 {
0531 return *t;
0532 }
0533 inline void variant_deref_(void const volatile *) noexcept
0534 {}
0535
0536 template<typename Variant>
0537 struct variant_get
0538 {
0539
0540
0541 template<std::size_t N>
0542 friend meta::_t<
0543 std::add_lvalue_reference<meta::at_c<meta::as_list<Variant>, N>>>
0544 get(Variant & var)
0545 {
0546 using elem_t = meta::_t<
0547 std::remove_reference<meta::at_c<meta::as_list<Variant>, N>>>;
0548 elem_t * elem = nullptr;
0549 auto & data_var = detail::variant_core_access::data(var);
0550 detail::variant_visit_(
0551 var.index(), data_var, detail::get_fn<elem_t, N>{&elem});
0552 return detail::variant_deref_(elem);
0553 }
0554 template<std::size_t N>
0555 friend meta::_t<
0556 std::add_lvalue_reference<meta::at_c<meta::as_list<Variant>, N> const>>
0557 get(Variant const & var)
0558 {
0559 using elem_t = meta::_t<
0560 std::remove_reference<meta::at_c<meta::as_list<Variant>, N> const>>;
0561 elem_t * elem = nullptr;
0562 auto & data_var = detail::variant_core_access::data(var);
0563 detail::variant_visit_(
0564 var.index(), data_var, detail::get_fn<elem_t, N>{&elem});
0565 return detail::variant_deref_(elem);
0566 }
0567 template<std::size_t N>
0568 friend meta::_t<
0569 std::add_rvalue_reference<meta::at_c<meta::as_list<Variant>, N>>>
0570 get(Variant && var)
0571 {
0572 using elem_t = meta::_t<
0573 std::remove_reference<meta::at_c<meta::as_list<Variant>, N>>>;
0574 elem_t * elem = nullptr;
0575 auto & data_var = detail::variant_core_access::data(var);
0576 detail::variant_visit_(
0577 var.index(), data_var, detail::get_fn<elem_t, N>{&elem});
0578 using res_t = meta::_t<
0579 std::add_rvalue_reference<meta::at_c<meta::as_list<Variant>, N>>>;
0580 return static_cast<res_t>(detail::variant_deref_(elem));
0581 }
0582 };
0583
0584 template<typename Variant,
0585 bool Trivial = std::is_trivially_destructible<meta::apply<
0586 meta::quote<variant_data>, meta::as_list<Variant>>>::value>
0587 struct variant_base : variant_get<Variant>
0588 {
0589 ~variant_base()
0590 {
0591 static_cast<Variant *>(this)->clear_();
0592 }
0593 };
0594 template<typename... Ts>
0595 struct variant_base<variant<Ts...>, true> : variant_get<variant<Ts...>>
0596 {};
0597
0598 template<typename Fun, typename Types, typename Indices, typename = void>
0599 struct variant_visit_results
0600 {};
0601 template<typename Fun, typename... Ts, std::size_t... Is>
0602 struct variant_visit_results<
0603 Fun, meta::list<Ts...>, meta::index_sequence<Is...>,
0604 meta::void_<invoke_result_t<Fun &, indexed_element<Ts, Is>>...>>
0605 {
0606 using type = variant<invoke_result_t<Fun &, indexed_element<Ts, Is>>...>;
0607 };
0608 template<typename Fun, typename... Ts>
0609 using variant_visit_results_t =
0610 meta::_t<variant_visit_results<Fun, meta::list<Ts...>,
0611 meta::make_index_sequence<sizeof...(Ts)>>>;
0612 }
0613
0614
0615
0616
0617 template<typename... Ts>
0618 struct variant
0619 : private detail::variant_data<Ts...>
0620 , private detail::variant_base<variant<Ts...>>
0621 {
0622 private:
0623 friend detail::variant_core_access;
0624 template<typename...>
0625 friend struct variant;
0626 friend detail::variant_base<variant, false>;
0627 template<std::size_t Index>
0628 using datum_t = detail::variant_datum_t<Index, Ts...>;
0629 template<typename T>
0630 using add_const_t = meta::if_<std::is_void<T>, void, T const>;
0631 using unbox_fn = detail::get_datum_fn;
0632
0633 detail::variant_data<Ts...> & data_() & noexcept
0634 {
0635 return *this;
0636 }
0637 detail::variant_data<Ts...> const & data_() const & noexcept
0638 {
0639 return *this;
0640 }
0641 detail::variant_data<Ts...> && data_() && noexcept
0642 {
0643 return static_cast<detail::variant_data<Ts...> &&>(*this);
0644 }
0645
0646 std::size_t index_;
0647
0648 void clear_() noexcept
0649 {
0650 if(valid())
0651 {
0652 detail::variant_visit_(index_, data_(), detail::delete_fn{}, identity{});
0653 index_ = (std::size_t)-1;
0654 }
0655 }
0656 template<typename That>
0657 void assign_(That && that)
0658 {
0659 if(that.valid())
0660 index_ = detail::variant_move_copy_(
0661 that.index_, data_(), ((That &&) that).data_());
0662 }
0663 constexpr variant(detail::empty_variant_tag) noexcept
0664 : detail::variant_data<Ts...>{}
0665 , index_((std::size_t)-1)
0666 {}
0667 template(typename... Args)(
0668 requires (sizeof...(Args) == sizeof...(Ts)))
0669 static constexpr bool all_convertible_to(int) noexcept
0670 {
0671 return and_v<convertible_to<Args, Ts>...>;
0672 }
0673 template<typename... Args>
0674 static constexpr bool all_convertible_to(long) noexcept
0675 {
0676 return false;
0677 }
0678
0679 public:
0680 CPP_member
0681 constexpr CPP_ctor(variant)()(
0682 noexcept(std::is_nothrow_default_constructible<datum_t<0>>::value)
0683 requires default_constructible<datum_t<0>>)
0684 : variant{emplaced_index<0>}
0685 {}
0686 template(std::size_t N, typename... Args)(
0687 requires constructible_from<datum_t<N>, Args...>)
0688 constexpr variant(emplaced_index_t<N>, Args &&... args) noexcept(
0689 std::is_nothrow_constructible<datum_t<N>, Args...>::value)
0690 : detail::variant_data<Ts...>{meta::size_t<N>{}, static_cast<Args &&>(args)...}
0691 , index_(N)
0692 {}
0693 template(std::size_t N, typename T, typename... Args)(
0694 requires constructible_from<datum_t<N>, std::initializer_list<T> &,
0695 Args...>)
0696 constexpr variant(
0697 emplaced_index_t<N>, std::initializer_list<T> il,
0698 Args &&... args) noexcept(std::
0699 is_nothrow_constructible<
0700 datum_t<N>, std::initializer_list<T> &,
0701 Args...>::value)
0702 : detail::variant_data<Ts...>{meta::size_t<N>{},
0703 il,
0704 static_cast<Args &&>(args)...}
0705 , index_(N)
0706 {}
0707 template(std::size_t N)(
0708 requires constructible_from<datum_t<N>, meta::nil_>)
0709 constexpr variant(emplaced_index_t<N>, meta::nil_)
0710 noexcept(std::is_nothrow_constructible<datum_t<N>, meta::nil_>::value)
0711 : detail::variant_data<Ts...>{meta::size_t<N>{}, meta::nil_{}}
0712 , index_(N)
0713 {}
0714 variant(variant && that)
0715 : detail::variant_data<Ts...>{}
0716 , index_(detail::variant_move_copy_(that.index(), data_(),
0717 std::move(that.data_())))
0718 {}
0719 variant(variant const & that)
0720 : detail::variant_data<Ts...>{}
0721 , index_(detail::variant_move_copy_(that.index(), data_(), that.data_()))
0722 {}
0723 template(typename... Args)(
0724 requires (!same_as<variant<Args...>, variant>) AND
0725 (all_convertible_to<Args...>(0)))
0726 variant(variant<Args...> that)
0727 : detail::variant_data<Ts...>{}
0728 , index_(detail::variant_move_copy_(that.index(), data_(),
0729 std::move(that.data_())))
0730 {}
0731 variant & operator=(variant && that)
0732 {
0733
0734 this->clear_();
0735 this->assign_(detail::move(that));
0736 return *this;
0737 }
0738 variant & operator=(variant const & that)
0739 {
0740
0741 this->clear_();
0742 this->assign_(that);
0743 return *this;
0744 }
0745 template(typename... Args)(
0746 requires (!same_as<variant<Args...>, variant>) AND
0747 (all_convertible_to<Args...>(0)))
0748 variant & operator=(variant<Args...> that)
0749 {
0750
0751 this->clear_();
0752 this->assign_(that);
0753 return *this;
0754 }
0755 static constexpr std::size_t size() noexcept
0756 {
0757 return sizeof...(Ts);
0758 }
0759 template(std::size_t N, typename... Args)(
0760 requires constructible_from<datum_t<N>, Args...>)
0761 void emplace(Args &&... args)
0762 {
0763 this->clear_();
0764 detail::construct_fn<N, Args &&...> fn{static_cast<Args &&>(args)...};
0765 detail::variant_visit_(N, data_(), std::ref(fn), identity{});
0766 index_ = N;
0767 }
0768 constexpr bool valid() const noexcept
0769 {
0770 return index() != (std::size_t)-1;
0771 }
0772 constexpr std::size_t index() const noexcept
0773 {
0774 return index_;
0775 }
0776 template<typename Fun>
0777 detail::variant_visit_results_t<composed<Fun, unbox_fn>, Ts...> visit(Fun fun)
0778 {
0779 detail::variant_visit_results_t<composed<Fun, unbox_fn>, Ts...> res{
0780 detail::empty_variant_tag{}};
0781 detail::variant_visit_(index_,
0782 data_(),
0783 detail::make_variant_visitor(
0784 res, compose(detail::move(fun), unbox_fn{})));
0785 return res;
0786 }
0787 template<typename Fun>
0788 detail::variant_visit_results_t<composed<Fun, unbox_fn>, add_const_t<Ts>...>
0789 visit(Fun fun) const
0790 {
0791 detail::variant_visit_results_t<composed<Fun, unbox_fn>, add_const_t<Ts>...>
0792 res{detail::empty_variant_tag{}};
0793 detail::variant_visit_(index_,
0794 data_(),
0795 detail::make_variant_visitor(
0796 res, compose(detail::move(fun), unbox_fn{})));
0797 return res;
0798 }
0799 template<typename Fun>
0800 detail::variant_visit_results_t<Fun, Ts...> visit_i(Fun fun)
0801 {
0802 detail::variant_visit_results_t<Fun, Ts...> res{detail::empty_variant_tag{}};
0803 detail::variant_visit_(
0804 index_, data_(), detail::make_variant_visitor(res, detail::move(fun)));
0805 return res;
0806 }
0807 template<typename Fun>
0808 detail::variant_visit_results_t<Fun, add_const_t<Ts>...> visit_i(Fun fun) const
0809 {
0810 detail::variant_visit_results_t<Fun, add_const_t<Ts>...> res{
0811 detail::empty_variant_tag{}};
0812 detail::variant_visit_(
0813 index_, data_(), detail::make_variant_visitor(res, detail::move(fun)));
0814 return res;
0815 }
0816 };
0817
0818 template(typename... Ts, typename... Us)(
0819 requires and_v<equality_comparable_with<Ts, Us>...>)
0820 bool operator==(variant<Ts...> const & lhs, variant<Us...> const & rhs)
0821 {
0822 return (!lhs.valid() && !rhs.valid()) ||
0823 (lhs.index() == rhs.index() &&
0824 detail::variant_equal_(lhs.index(),
0825 detail::variant_core_access::data(lhs),
0826 detail::variant_core_access::data(rhs)));
0827 }
0828
0829 template(typename... Ts, typename... Us)(
0830 requires and_v<equality_comparable_with<Ts, Us>...>)
0831 bool operator!=(variant<Ts...> const & lhs, variant<Us...> const & rhs)
0832 {
0833 return !(lhs == rhs);
0834 }
0835
0836
0837
0838 template(std::size_t N, typename... Ts, typename... Args)(
0839 requires constructible_from<detail::variant_datum_t<N, Ts...>, Args...>)
0840 void emplace(variant<Ts...> & var, Args &&... args)
0841 {
0842 var.template emplace<N>(static_cast<Args &&>(args)...);
0843 }
0844
0845
0846
0847 template<typename Var>
0848 struct variant_unique
0849 {};
0850
0851 template<typename... Ts>
0852 struct variant_unique<variant<Ts...>>
0853 {
0854 using type = meta::apply<meta::quote<variant>, meta::unique<meta::list<Ts...>>>;
0855 };
0856
0857 template<typename Var>
0858 using variant_unique_t = meta::_t<variant_unique<Var>>;
0859
0860
0861
0862 template<typename... Ts>
0863 variant_unique_t<variant<Ts...>> unique_variant(variant<Ts...> const & var)
0864 {
0865 using From = variant<Ts...>;
0866 using To = variant_unique_t<From>;
0867 auto res = detail::variant_core_access::make_empty(meta::id<To>{});
0868 var.visit_i(detail::unique_visitor<To, From>{&res});
0869 RANGES_EXPECT(res.valid());
0870 return res;
0871 }
0872
0873 }
0874
0875 RANGES_DIAGNOSTIC_PUSH
0876 RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
0877
0878 namespace std
0879 {
0880 template<typename... Ts>
0881 struct tuple_size<::ranges::variant<Ts...>> : tuple_size<tuple<Ts...>>
0882 {};
0883
0884 template<size_t I, typename... Ts>
0885 struct tuple_element<I, ::ranges::variant<Ts...>> : tuple_element<I, tuple<Ts...>>
0886 {};
0887 }
0888
0889 RANGES_DIAGNOSTIC_POP
0890
0891 #include <range/v3/detail/epilogue.hpp>
0892
0893 #endif