13#ifndef RANGES_V3_DETAIL_VARIANT_HPP
14#define RANGES_V3_DETAIL_VARIANT_HPP
37#include <range/v3/detail/prologue.hpp>
41 template<std::
size_t I>
42 struct emplaced_index_t;
44 template<std::
size_t I>
48#if RANGES_CXX_INLINE_VARIABLES < RANGES_CXX_INLINE_VARIABLES_17
51 template<std::
size_t I>
55 template<std::
size_t I>
56 inline constexpr emplaced_index_t<I> emplaced_index{};
62 : std::logic_error(what_arg)
65 : std::logic_error(what_arg)
69 template<
typename T, std::
size_t Index>
73 std::add_pointer_t<T> t_;
77 : t_(std::addressof(t))
79 constexpr T & get()
const noexcept
84 template<
typename T, std::
size_t Index>
92 : t_(std::addressof(t))
94 constexpr T && get()
const noexcept
96 return static_cast<T &&
>(*t_);
99 template<std::
size_t Index>
102 void get()
const noexcept
109 struct indexed_element_fn;
111 template(
typename I,
typename S,
typename O)(
113 O uninitialized_copy(I first, S last, O out)
115 for(; first != last; ++first, ++out)
116 ::new((
void *)std::addressof(*out)) iter_value_t<O>(*first);
120 template(
typename I,
typename S,
typename O)(
121 requires sized_sentinel_for<S, I>)
122 O uninitialized_copy(I first, S last, O out)
124 return std::uninitialized_copy_n(first, (last - first), out);
127 template<
typename I,
typename O>
128 O uninitialized_copy(I first, I last, O out)
130 return std::uninitialized_copy(first, last, out);
133 template<
typename T,
typename Index>
137 template<
typename,
typename>
138 friend struct indexed_datum;
143 constexpr CPP_ctor(indexed_datum)()(
144 noexcept(std::is_nothrow_default_constructible<T>::value)
145 requires default_constructible<T>)
148 template(
typename... Ts)(
149 requires constructible_from<T, Ts...> AND (
sizeof...(Ts) != 0))
150 constexpr indexed_datum(Ts &&... ts)
noexcept(
151 std::is_nothrow_constructible<T, Ts...>::value)
152 : datum_(static_cast<Ts &&>(ts)...)
154 template(
typename U)(
155 requires (!same_as<T, U>) AND convertible_to<U, T>)
156 constexpr indexed_datum(indexed_datum<U, Index> that)
157 noexcept(std::is_nothrow_constructible<T, U>::value)
158 : datum_(std::move(that.datum_))
160 constexpr auto ref() noexcept
162 return indexed_element<T, Index::value>{datum_};
164 constexpr auto ref() const noexcept
166 return indexed_element<T const, Index::value>{datum_};
168 constexpr T & get() noexcept
172 constexpr T
const & get() const noexcept
178 template<
typename T, std::
size_t N,
typename Index>
179 struct indexed_datum<T[N], Index>;
181 template<
typename T,
typename Index>
182 struct indexed_datum<T &, Index>
185 template<
typename,
typename>
186 friend struct indexed_datum;
190 constexpr indexed_datum(T & t) noexcept
191 : t_(std::addressof(t))
193 constexpr T & get() const noexcept
197 constexpr auto ref() const noexcept
199 return indexed_element<T &, Index::value>{*t_};
202 template<
typename T,
typename Index>
203 struct indexed_datum<T &&, Index>
206 template<
typename,
typename>
207 friend struct indexed_datum;
211 constexpr indexed_datum(T && t) noexcept
212 : t_(std::addressof(t))
214 constexpr T && get() const noexcept
216 return static_cast<T &&
>(*t_);
218 constexpr auto ref() const noexcept
220 return indexed_element<T &&, Index::value>{
static_cast<T &&
>(*t_)};
223 template<
typename Index>
224 struct indexed_datum<void, Index>
226 void get() const noexcept
228 constexpr indexed_element<void, Index::value> ref() const noexcept
234 template<std::size_t Index,
typename... Ts>
235 using variant_datum_t =
239 using variant_nil = indexed_datum<void, meta::npos>;
241 template<
typename Ts,
248 using type = indexed_datum<void, meta::npos>;
251 template<
typename T,
typename... Ts>
252 struct variant_data_<
meta::list<T, Ts...>, true>
266 template<
typename... Args>
268 std::is_nothrow_constructible<head_t, Args...>::value)
269 : head{((Args &&) args)...}
271 template<std::size_t N,
typename... Args>
273 std::is_nothrow_constructible<tail_t,
meta::size_t<N - 1>,
275 : tail{
meta::
size_t<N - 1>{}, ((Args &&) args)...}
280 template<
typename T,
typename... Ts>
281 struct variant_data_<
meta::list<T, Ts...>, false>
297 template<
typename... Args>
299 std::is_nothrow_constructible<head_t, Args...>::value)
300 : head{((Args &&) args)...}
302 template<std::size_t N,
typename... Args>
304 std::is_nothrow_constructible<tail_t,
meta::size_t<N - 1>,
306 : tail{
meta::
size_t<N - 1>{}, ((Args &&) args)...}
311 template<
typename... Ts>
316 inline std::size_t variant_move_copy_(std::size_t, variant_nil, variant_nil)
320 template<
typename Data0,
typename Data1>
321 std::size_t variant_move_copy_(std::size_t n, Data0 & self, Data1 && that)
323 using Head =
typename Data0::head_t;
325 ? ((void)::new((
void *)&self.head) Head(((Data1 &&) that).head), 0)
326 : variant_move_copy_(n - 1, self.tail, ((Data1 &&) that).tail) + 1;
328 constexpr bool variant_equal_(std::size_t, variant_nil, variant_nil)
332 template<
typename Data0,
typename Data1>
333 constexpr bool variant_equal_(std::size_t n, Data0
const & self,
336 return n == 0 ? self.head.get() == that.head.get()
337 : variant_equal_(n - 1, self.tail, that.tail);
339 template<
typename Fun,
typename Proj = indexed_element_fn>
340 constexpr int variant_visit_(std::size_t, variant_nil, Fun, Proj = {})
342 return (RANGES_EXPECT(
false), 0);
344 template<
typename Data,
typename Fun,
typename Proj = indexed_element_fn>
345 constexpr int variant_visit_(std::size_t n, Data & self, Fun fun, Proj proj = {})
347 return 0 == n ? ((void)
invoke(fun,
invoke(proj, self.head)), 0)
348 : detail::variant_visit_(
349 n - 1, self.tail, detail::move(fun), detail::move(proj));
355 decltype(
auto)
operator()(T && t)
const noexcept
361 struct indexed_element_fn
364 decltype(
auto)
operator()(T && t)
const noexcept
370 struct empty_variant_tag
373 struct variant_core_access
375 template<
typename... Ts>
376 static constexpr variant_data<Ts...> & data(variant<Ts...> & var)
noexcept
380 template<
typename... Ts>
381 static constexpr variant_data<Ts...>
const & data(
382 variant<Ts...>
const & var)
noexcept
386 template<
typename... Ts>
387 static constexpr variant_data<Ts...> && data(variant<Ts...> && var)
noexcept
389 return detail::move(var.data_());
391 template<
typename... Ts>
392 static variant<Ts...> make_empty(
meta::id<variant<Ts...>> = {})
noexcept
394 return variant<Ts...>{empty_variant_tag{}};
401 void operator()(T
const & t)
const noexcept
407 template<std::size_t N,
typename... Ts>
410 std::tuple<Ts...> args_;
412 template<
typename U, std::size_t... Is>
414 std::is_nothrow_constructible<U, Ts...>::value)
416 ::new((
void *)std::addressof(u))
417 U(
static_cast<Ts &&
>(std::get<Is>(args_))...);
420 construct_fn(Ts &&... ts)
noexcept(
421 std::is_nothrow_constructible<std::tuple<Ts...>, Ts...>::value)
422 : args_{static_cast<Ts &&>(ts)...}
424 template<
typename U, std::
size_t M>
425 [[noreturn]] meta::if_c<N != M> operator()(
428 RANGES_EXPECT(
false);
433 u)
noexcept(std::is_nothrow_constructible<U, Ts...>::value)
440 u)
noexcept(std::is_nothrow_constructible<detail::decay_t<U>,
447 template<
typename T, std::
size_t N>
452 template<
typename U, std::
size_t M>
453 [[noreturn]] meta::if_c<M != N> operator()(indexed_element<U, M>)
const
455 throw bad_variant_access(
"bad variant access");
458 void operator()(indexed_element<U, N> t)
const noexcept
460 *t_ = std::addressof(t.get());
463 void operator()(indexed_element<U &&, N> t)
const noexcept
466 *t_ = std::addressof(u);
468 void operator()(indexed_element<void, N>)
const noexcept
472 template<
typename Variant, std::
size_t N>
477 template<
typename...Ts>
478 auto CPP_auto_fun(
operator())(Ts &&...ts) (
const)
480 return var_->template emplace<N>(
static_cast<Ts &&
>(ts)...)
485 template<
typename Fun,
typename Variant>
486 struct variant_visitor
492 template<
typename U, std::
size_t N>
493 auto CPP_auto_fun(
operator())(indexed_element<U, N> u)
495 return compose(emplace_fn<Variant, N>{var_}, fun_)(u)
500 template<
typename Variant,
typename Fun>
501 variant_visitor<Fun, Variant> make_variant_visitor(
503 Fun fun)
noexcept(std::is_nothrow_move_constructible<Fun>::value)
505 return {detail::move(fun), &var};
508 template<
typename To,
typename From>
509 struct unique_visitor;
511 template<
typename... To,
typename... From>
512 struct unique_visitor<variant<To...>, variant<From...>>
514 variant<To...> * var_;
516 template<
typename T, std::
size_t N>
517 void operator()(indexed_element<T, N> t)
const
520 static_assert(RANGES_IS_SAME(T
const, E
const),
521 "Is indexed_element broken?");
523 static constexpr std::size_t M =
sizeof...(To) - F::size();
524 compose(emplace_fn<variant<To...>, M>{var_}, get_datum_fn{})(t);
529 constexpr T & variant_deref_(T * t)
noexcept
533 inline void variant_deref_(
void const volatile *)
noexcept
536 template<
typename Variant>
541 template<std::
size_t N>
543 std::add_lvalue_reference<meta::at_c<meta::as_list<Variant>, N>>>
547 std::remove_reference<meta::at_c<meta::as_list<Variant>, N>>>;
548 elem_t * elem =
nullptr;
549 auto & data_var = detail::variant_core_access::data(var);
550 detail::variant_visit_(
551 var.index(), data_var, detail::get_fn<elem_t, N>{&elem});
552 return detail::variant_deref_(elem);
554 template<std::
size_t N>
556 std::add_lvalue_reference<meta::at_c<meta::as_list<Variant>, N>
const>>
557 get(Variant
const & var)
560 std::remove_reference<meta::at_c<meta::as_list<Variant>, N>
const>>;
561 elem_t * elem =
nullptr;
562 auto & data_var = detail::variant_core_access::data(var);
563 detail::variant_visit_(
564 var.index(), data_var, detail::get_fn<elem_t, N>{&elem});
565 return detail::variant_deref_(elem);
567 template<std::
size_t N>
569 std::add_rvalue_reference<meta::at_c<meta::as_list<Variant>, N>>>
573 std::remove_reference<meta::at_c<meta::as_list<Variant>, N>>>;
574 elem_t * elem =
nullptr;
575 auto & data_var = detail::variant_core_access::data(var);
576 detail::variant_visit_(
577 var.index(), data_var, detail::get_fn<elem_t, N>{&elem});
579 std::add_rvalue_reference<meta::at_c<meta::as_list<Variant>, N>>>;
580 return static_cast<res_t
>(detail::variant_deref_(elem));
584 template<
typename Variant,
585 bool Trivial = std::is_trivially_destructible<
meta::apply<
587 struct variant_base : variant_get<Variant>
591 static_cast<Variant *
>(
this)->clear_();
594 template<
typename... Ts>
595 struct variant_base<variant<Ts...>, true> : variant_get<variant<Ts...>>
598 template<
typename Fun,
typename Types,
typename Indices,
typename =
void>
599 struct variant_visit_results
601 template<
typename Fun,
typename... Ts, std::size_t... Is>
602 struct variant_visit_results<
604 meta::void_<invoke_result_t<Fun &, indexed_element<Ts, Is>>...>>
606 using type = variant<invoke_result_t<Fun &, indexed_element<Ts, Is>>...>;
608 template<
typename Fun,
typename... Ts>
609 using variant_visit_results_t =
617 template<
typename... Ts>
619 :
private detail::variant_data<Ts...>
620 ,
private detail::variant_base<variant<Ts...>>
623 friend detail::variant_core_access;
624 template<
typename...>
626 friend detail::variant_base<variant, false>;
627 template<std::
size_t Index>
628 using datum_t = detail::variant_datum_t<Index, Ts...>;
631 using unbox_fn = detail::get_datum_fn;
633 detail::variant_data<Ts...> & data_() &
noexcept
637 detail::variant_data<Ts...>
const & data_()
const &
noexcept
641 detail::variant_data<Ts...> && data_() &&
noexcept
643 return static_cast<detail::variant_data<Ts...
> &&>(*this);
648 void clear_()
noexcept
652 detail::variant_visit_(index_, data_(), detail::delete_fn{},
identity{});
653 index_ = (std::size_t)-1;
656 template<
typename That>
657 void assign_(That && that)
660 index_ = detail::variant_move_copy_(
661 that.index_, data_(), ((That &&) that).data_());
663 constexpr variant(detail::empty_variant_tag) noexcept
664 : detail::variant_data<Ts...>{}
665 , index_((std::size_t)-1)
667 template(
typename... Args)(
668 requires (
sizeof...(Args) ==
sizeof...(Ts)))
669 static constexpr bool all_convertible_to(
int)
noexcept
671 return and_v<convertible_to<Args, Ts>...>;
673 template<
typename... Args>
674 static constexpr bool all_convertible_to(
long)
noexcept
682 noexcept(std::is_nothrow_default_constructible<datum_t<0>>::value)
683 requires default_constructible<datum_t<0>>)
686 template(std::size_t N,
typename... Args)(
687 requires constructible_from<datum_t<N>, Args...>)
689 std::is_nothrow_constructible<datum_t<N>, Args...>::value)
690 : detail::variant_data<Ts...>{
meta::size_t<N>{},
static_cast<Args &&
>(args)...}
693 template(std::size_t N,
typename T,
typename... Args)(
694 requires constructible_from<datum_t<N>, std::initializer_list<T> &,
698 Args &&... args)
noexcept(std::
699 is_nothrow_constructible<
700 datum_t<N>, std::initializer_list<T> &,
704 static_cast<Args &&
>(args)...}
707 template(std::size_t N)(
708 requires constructible_from<datum_t<N>,
meta::nil_>)
710 noexcept(std::is_nothrow_constructible<datum_t<N>,
meta::nil_>::value)
715 : detail::variant_data<Ts...>{}
716 , index_(detail::variant_move_copy_(that.index(), data_(),
717 std::move(that.data_())))
720 : detail::variant_data<Ts...>{}
721 , index_(detail::variant_move_copy_(that.index(), data_(), that.data_()))
723 template(
typename... Args)(
725 (all_convertible_to<Args...>(0)))
727 : detail::variant_data<Ts...>{}
728 , index_(detail::variant_move_copy_(that.index(), data_(),
729 std::move(that.data_())))
735 this->assign_(detail::move(that));
745 template(
typename... Args)(
747 (all_convertible_to<Args...>(0)))
755 static constexpr std::size_t size()
noexcept
757 return sizeof...(Ts);
759 template(std::size_t N,
typename... Args)(
760 requires constructible_from<datum_t<N>, Args...>)
761 void emplace(Args &&... args)
764 detail::construct_fn<N, Args &&...> fn{
static_cast<Args &&
>(args)...};
765 detail::variant_visit_(N, data_(), std::ref(fn),
identity{});
768 constexpr bool valid()
const noexcept
770 return index() != (std::size_t)-1;
772 constexpr std::size_t index()
const noexcept
776 template<
typename Fun>
777 detail::variant_visit_results_t<composed<Fun, unbox_fn>, Ts...> visit(Fun fun)
779 detail::variant_visit_results_t<composed<Fun, unbox_fn>, Ts...> res{
780 detail::empty_variant_tag{}};
781 detail::variant_visit_(index_,
783 detail::make_variant_visitor(
784 res, compose(detail::move(fun), unbox_fn{})));
787 template<
typename Fun>
788 detail::variant_visit_results_t<composed<Fun, unbox_fn>, add_const_t<Ts>...>
791 detail::variant_visit_results_t<composed<Fun, unbox_fn>, add_const_t<Ts>...>
792 res{detail::empty_variant_tag{}};
793 detail::variant_visit_(index_,
795 detail::make_variant_visitor(
796 res, compose(detail::move(fun), unbox_fn{})));
799 template<
typename Fun>
800 detail::variant_visit_results_t<Fun, Ts...> visit_i(Fun fun)
802 detail::variant_visit_results_t<Fun, Ts...> res{detail::empty_variant_tag{}};
803 detail::variant_visit_(
804 index_, data_(), detail::make_variant_visitor(res, detail::move(fun)));
807 template<
typename Fun>
808 detail::variant_visit_results_t<Fun, add_const_t<Ts>...> visit_i(Fun fun)
const
810 detail::variant_visit_results_t<Fun, add_const_t<Ts>...> res{
811 detail::empty_variant_tag{}};
812 detail::variant_visit_(
813 index_, data_(), detail::make_variant_visitor(res, detail::move(fun)));
818 template(
typename... Ts,
typename... Us)(
819 requires and_v<equality_comparable_with<Ts, Us>...>)
822 return (!lhs.valid() && !rhs.valid()) ||
823 (lhs.index() == rhs.index() &&
824 detail::variant_equal_(lhs.index(),
825 detail::variant_core_access::data(lhs),
826 detail::variant_core_access::data(rhs)));
829 template(
typename... Ts,
typename... Us)(
830 requires and_v<equality_comparable_with<Ts, Us>...>)
831 bool operator!=(variant<Ts...>
const & lhs, variant<Us...>
const & rhs)
833 return !(lhs == rhs);
838 template(std::size_t N,
typename... Ts,
typename... Args)(
839 requires constructible_from<detail::variant_datum_t<N, Ts...>, Args...>)
840 void emplace(variant<Ts...> & var, Args &&... args)
842 var.template emplace<N>(
static_cast<Args &&
>(args)...);
847 template<
typename Var>
848 struct variant_unique
851 template<
typename... Ts>
857 template<
typename Var>
862 template<
typename... Ts>
866 using To = variant_unique_t<From>;
867 auto res = detail::variant_core_access::make_empty(
meta::id<To>{});
868 var.visit_i(detail::unique_visitor<To, From>{&res});
869 RANGES_EXPECT(res.valid());
875RANGES_DIAGNOSTIC_PUSH
876RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
880 template<
typename... Ts>
884 template<
size_t I,
typename... Ts>
891#include <range/v3/detail/epilogue.hpp>
The sized_sentinel_for concept.
_t< detail::make_indices_< N, index_sequence< 0 >, detail::strategy_(1, N)> > make_index_sequence
Generate index_sequence containing integer constants [0,1,2,...,N-1].
Definition meta.hpp:473
std::integral_constant< std::size_t, N > size_t
An integral constant wrapper for std::size_t.
Definition meta.hpp:163
typename T::type _t
Type alias for T::type.
Definition meta.hpp:141
_t< extension::apply< Fn, L > > apply
Applies the invocable Fn using the types in the type list L as arguments.
Definition meta.hpp:1030
typename Fn::template invoke< Args... > invoke
Evaluate the invocable Fn with the arguments Args.
Definition meta.hpp:541
_t< detail::at_< L, N > > at_c
Return the N th element in the meta::list L.
Definition meta.hpp:1962
_t< detail::as_list_< detail::uncvref_t< Sequence > > > as_list
Turn a type into an instance of meta::list in a way determined by meta::apply.
Definition meta.hpp:2961
_t< detail::_if_< list< Args... > > > if_
Select one type or another depending on a compile-time Boolean.
Definition meta.hpp:1247
drop< L, min< find_index< L, T >, size< L > > > find
Return the tail of the list L starting at the first occurrence of T, if any such element exists; the ...
Definition meta.hpp:2388
void void_
An alias for void.
Definition meta.hpp:597
Definition variant.hpp:60
Definition variant.hpp:46
Definition identity.hpp:25
Definition variant.hpp:71
Definition static_const.hpp:22
Definition variant.hpp:621