|
- // Range v3 library
- //
- // Copyright Eric Niebler 2014-present
- //
- // Use, modification and distribution is subject to the
- // Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- //
- // Project home: https://github.com/ericniebler/range-v3
- //
-
- #ifndef RANGES_V3_DETAIL_VARIANT_HPP
- #define RANGES_V3_DETAIL_VARIANT_HPP
-
- #include <iterator>
- #include <memory>
- #include <new>
- #include <stdexcept>
- #include <tuple>
- #include <type_traits>
- #include <utility>
-
- #include <meta/meta.hpp>
-
- #include <concepts/concepts.hpp>
-
- #include <range/v3/range_fwd.hpp>
-
- #include <range/v3/functional/compose.hpp>
- #include <range/v3/functional/identity.hpp>
- #include <range/v3/functional/invoke.hpp>
- #include <range/v3/functional/reference_wrapper.hpp>
- #include <range/v3/iterator/concepts.hpp>
- #include <range/v3/iterator/traits.hpp>
- #include <range/v3/utility/get.hpp>
-
- namespace ranges
- {
- template<std::size_t I>
- struct emplaced_index_t;
-
- template<std::size_t I>
- struct emplaced_index_t : meta::size_t<I>
- {};
-
- /// \cond
- #if !RANGES_CXX_VARIABLE_TEMPLATES
- template<std::size_t I>
- inline emplaced_index_t<I> emplaced_index()
- {
- return {};
- }
- template<std::size_t I>
- using _emplaced_index_t_ = emplaced_index_t<I> (&)();
- #define RANGES_EMPLACED_INDEX_T(I) _emplaced_index_t_<I>
- #else
- /// \endcond
-
- #if RANGES_CXX_INLINE_VARIABLES < RANGES_CXX_INLINE_VARIABLES_17
- namespace
- {
- template<std::size_t I>
- constexpr auto & emplaced_index = static_const<emplaced_index_t<I>>::value;
- }
- #else // RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17
- template<std::size_t I>
- inline constexpr emplaced_index_t<I> emplaced_index{};
- #endif // RANGES_CXX_INLINE_VARIABLES
-
- /// \cond
- #define RANGES_EMPLACED_INDEX_T(I) emplaced_index_t<I>
- #endif
- /// \endcond
-
- struct bad_variant_access : std::logic_error
- {
- explicit bad_variant_access(std::string const & what_arg)
- : std::logic_error(what_arg)
- {}
- explicit bad_variant_access(char const * what_arg)
- : std::logic_error(what_arg)
- {}
- };
-
- template<typename T, std::size_t Index>
- struct indexed_element
- {
- private:
- reference_wrapper<T> ref_;
-
- public:
- constexpr indexed_element(reference_wrapper<T> r) noexcept
- : ref_(r)
- {}
- constexpr decltype(auto) get() const noexcept
- {
- return ref_.get();
- }
- };
- template<std::size_t Index>
- struct indexed_element<void, Index>
- {
- void get() const noexcept
- {}
- };
-
- /// \cond
- namespace detail
- {
- struct indexed_element_fn;
-
- template<typename I, typename S, typename O>
- auto uninitialized_copy(I first, S last, O out) -> CPP_ret(O)( //
- requires(!sized_sentinel_for<S, I>))
- {
- for(; first != last; ++first, ++out)
- ::new((void *)std::addressof(*out)) iter_value_t<O>(*first);
- return out;
- }
-
- template<typename I, typename S, typename O>
- auto uninitialized_copy(I first, S last, O out) -> CPP_ret(O)( //
- requires sized_sentinel_for<S, I>)
- {
- return std::uninitialized_copy_n(first, (last - first), out);
- }
-
- template<typename I, typename O>
- O uninitialized_copy(I first, I last, O out)
- {
- return std::uninitialized_copy(first, last, out);
- }
-
- template<typename T, typename Index>
- struct indexed_datum
- {
- private:
- template<typename, typename>
- friend struct indexed_datum;
- T datum_;
-
- public:
- CPP_member
- constexpr CPP_ctor(indexed_datum)()( //
- noexcept(std::is_nothrow_default_constructible<T>::value) //
- requires default_constructible<T>)
- : datum_{}
- {}
- CPP_template(typename... Ts)( //
- requires constructible_from<T, Ts...> && (sizeof...(Ts) != 0)) //
- constexpr indexed_datum(Ts &&... ts) noexcept(
- std::is_nothrow_constructible<T, Ts...>::value)
- : datum_(static_cast<Ts &&>(ts)...)
- {}
- template<typename U>
- constexpr CPP_ctor(indexed_datum)(indexed_datum<U, Index> that)( //
- noexcept(std::is_nothrow_constructible<T, U>::value) //
- requires(!same_as<T, U>) &&
- convertible_to<U, T>)
- : datum_(std::move(that.datum_))
- {}
- constexpr indexed_element<T, Index::value> ref() noexcept
- {
- return {datum_};
- }
- constexpr indexed_element<T const, Index::value> ref() const noexcept
- {
- return {datum_};
- }
- constexpr T & get() noexcept
- {
- return datum_;
- }
- constexpr T const & get() const noexcept
- {
- return datum_;
- }
- };
-
- template<typename T, std::size_t N, typename Index>
- struct indexed_datum<T[N], Index>;
-
- template<typename T, typename Index>
- struct indexed_datum<T &, Index>
- {
- private:
- template<typename, typename>
- friend struct indexed_datum;
- reference_wrapper<T &> ref_;
-
- public:
- constexpr indexed_datum(reference_wrapper<T &> ref) noexcept
- : ref_(ref)
- {}
- constexpr indexed_element<T &, Index::value> ref() const noexcept
- {
- return {ref_.get()};
- }
- };
- template<typename T, typename Index>
- struct indexed_datum<T &&, Index>
- {
- private:
- template<typename, typename>
- friend struct indexed_datum;
- reference_wrapper<T &&> ref_;
-
- public:
- constexpr indexed_datum(reference_wrapper<T &&> ref) noexcept
- : ref_(ref)
- {}
- constexpr indexed_element<T &&, Index::value> ref() const noexcept
- {
- return {ref_.get()};
- }
- };
- template<typename Index>
- struct indexed_datum<void, Index>
- {
- void get() const noexcept
- {}
- constexpr indexed_element<void, Index::value> ref() const noexcept
- {
- return {};
- }
- };
-
- template<std::size_t Index, typename... Ts>
- using variant_datum_t =
- detail::indexed_datum<meta::at_c<meta::list<Ts...>, Index>,
- meta::size_t<Index>>;
- } // namespace detail
-
- template<std::size_t N, typename... Ts, typename... Args>
- meta::if_c<(bool)constructible_from<detail::variant_datum_t<N, Ts...>, Args...>>
- emplace(variant<Ts...> &, Args &&...);
-
- namespace detail
- {
- using variant_nil = indexed_datum<void, meta::npos>;
-
- template<typename Ts,
- bool Trivial = meta::apply<
- meta::quote<meta::and_>,
- meta::transform<Ts, meta::quote<std::is_trivially_destructible>>>::
- type::value>
- struct variant_data_
- {
- using type = indexed_datum<void, meta::npos>;
- };
-
- template<typename T, typename... Ts>
- struct variant_data_<meta::list<T, Ts...>, true>
- {
- struct type
- {
- using head_t = T;
- using tail_t = meta::_t<variant_data_<meta::list<Ts...>>>;
- union
- {
- head_t head;
- tail_t tail;
- };
-
- type() noexcept
- {}
- template<typename... Args>
- constexpr type(meta::size_t<0>, Args &&... args) noexcept(
- std::is_nothrow_constructible<head_t, Args...>::value)
- : head{((Args &&) args)...}
- {}
- template<std::size_t N, typename... Args>
- constexpr type(meta::size_t<N>, Args &&... args) noexcept(
- std::is_nothrow_constructible<tail_t, meta::size_t<N - 1>,
- Args...>::value)
- : tail{meta::size_t<N - 1>{}, ((Args &&) args)...}
- {}
- };
- };
-
- template<typename T, typename... Ts>
- struct variant_data_<meta::list<T, Ts...>, false>
- {
- struct type
- {
- using head_t = T;
- using tail_t = meta::_t<variant_data_<meta::list<Ts...>>>;
- union
- {
- head_t head;
- tail_t tail;
- };
-
- type() noexcept
- {}
- ~type()
- {}
- template<typename... Args>
- constexpr type(meta::size_t<0>, Args &&... args) noexcept(
- std::is_nothrow_constructible<head_t, Args...>::value)
- : head{((Args &&) args)...}
- {}
- template<std::size_t N, typename... Args>
- constexpr type(meta::size_t<N>, Args &&... args) noexcept(
- std::is_nothrow_constructible<tail_t, meta::size_t<N - 1>,
- Args...>::value)
- : tail{meta::size_t<N - 1>{}, ((Args &&) args)...}
- {}
- };
- };
-
- template<typename... Ts>
- using variant_data = meta::_t<variant_data_<meta::transform<
- meta::list<Ts...>, meta::as_list<meta::make_index_sequence<sizeof...(Ts)>>,
- meta::quote<indexed_datum>>>>;
-
- inline std::size_t variant_move_copy_(std::size_t, variant_nil, variant_nil)
- {
- return 0;
- }
- template<typename Data0, typename Data1>
- std::size_t variant_move_copy_(std::size_t n, Data0 & self, Data1 && that)
- {
- using Head = typename Data0::head_t;
- return 0 == n
- ? ((void)::new((void *)&self.head) Head(((Data1 &&) that).head), 0)
- : variant_move_copy_(n - 1, self.tail, ((Data1 &&) that).tail) + 1;
- }
- constexpr bool variant_equal_(std::size_t, variant_nil, variant_nil)
- {
- return true;
- }
- template<typename Data0, typename Data1>
- constexpr bool variant_equal_(std::size_t n, Data0 const & self,
- Data1 const & that)
- {
- return n == 0 ? self.head.get() == that.head.get()
- : variant_equal_(n - 1, self.tail, that.tail);
- }
- template<typename Fun, typename Proj = indexed_element_fn>
- constexpr int variant_visit_(std::size_t, variant_nil, Fun, Proj = {})
- {
- return (RANGES_EXPECT(false), 0);
- }
- template<typename Data, typename Fun, typename Proj = indexed_element_fn>
- constexpr int variant_visit_(std::size_t n, Data & self, Fun fun, Proj proj = {})
- {
- return 0 == n ? ((void)invoke(fun, invoke(proj, self.head)), 0)
- : detail::variant_visit_(
- n - 1, self.tail, detail::move(fun), detail::move(proj));
- }
-
- struct get_datum_fn
- {
- template<typename T>
- decltype(auto) operator()(T && t) const noexcept
- {
- return t.get();
- }
- };
-
- struct indexed_element_fn
- {
- template<typename T>
- decltype(auto) operator()(T && t) const noexcept
- {
- return t.ref();
- }
- };
-
- struct empty_variant_tag
- {};
-
- struct variant_core_access
- {
- template<typename... Ts>
- static constexpr variant_data<Ts...> & data(variant<Ts...> & var) noexcept
- {
- return var.data_();
- }
- template<typename... Ts>
- static constexpr variant_data<Ts...> const & data(
- variant<Ts...> const & var) noexcept
- {
- return var.data_();
- }
- template<typename... Ts>
- static constexpr variant_data<Ts...> && data(variant<Ts...> && var) noexcept
- {
- return detail::move(var.data_());
- }
- template<typename... Ts>
- static variant<Ts...> make_empty(meta::id<variant<Ts...>> = {}) noexcept
- {
- return variant<Ts...>{empty_variant_tag{}};
- }
- };
-
- struct delete_fn
- {
- template<typename T>
- void operator()(T const & t) const noexcept
- {
- t.~T();
- }
- };
-
- template<std::size_t N, typename... Ts>
- struct construct_fn
- {
- std::tuple<Ts...> args_;
-
- template<typename U, std::size_t... Is>
- void construct_(U & u, meta::index_sequence<Is...>) noexcept(
- std::is_nothrow_constructible<U, Ts...>::value)
- {
- ::new((void *)std::addressof(u))
- U(static_cast<Ts &&>(std::get<Is>(args_))...);
- }
-
- construct_fn(Ts &&... ts) noexcept(
- std::is_nothrow_constructible<std::tuple<Ts...>, Ts...>::value)
- : args_{static_cast<Ts &&>(ts)...}
- {}
- template<typename U, std::size_t M>
- [[noreturn]] meta::if_c<N != M> operator()(
- indexed_datum<U, meta::size_t<M>> &) noexcept
- {
- RANGES_EXPECT(false);
- }
- template<typename U>
- meta::if_<std::is_object<U>> operator()(
- indexed_datum<U, meta::size_t<N>> &
- u) noexcept(std::is_nothrow_constructible<U, Ts...>::value)
- {
- this->construct_(u.get(), meta::make_index_sequence<sizeof...(Ts)>{});
- }
- template<typename U>
- meta::if_<meta::not_<std::is_object<U>>> operator()(
- indexed_datum<U, meta::size_t<N>> &
- u) noexcept(std::is_nothrow_constructible<detail::decay_t<U>,
- Ts...>::value)
- {
- this->construct_(u, meta::make_index_sequence<sizeof...(Ts)>{});
- }
- };
-
- template<typename T, std::size_t N>
- struct get_fn
- {
- T ** t_;
-
- template<typename U, std::size_t M>
- [[noreturn]] meta::if_c<M != N> operator()(indexed_element<U, M>) const
- {
- throw bad_variant_access("bad variant access");
- }
- template<typename U>
- void operator()(indexed_element<U, N> t) const noexcept
- {
- *t_ = std::addressof(t.get());
- }
- template<typename U>
- void operator()(indexed_element<U &&, N> t) const noexcept
- {
- U && u = t.get();
- *t_ = std::addressof(u);
- }
- void operator()(indexed_element<void, N>) const noexcept
- {}
- };
-
- template<typename Variant, std::size_t N>
- struct emplace_fn
- {
- Variant * var_;
- // clang-format off
- template<typename...Ts>
- auto CPP_auto_fun(operator())(Ts &&...ts) (const)
- (
- return ranges::emplace<N>(*var_, static_cast<Ts &&>(ts)...)
- )
- // clang-format on
- };
-
- template<typename Fun, typename Variant>
- struct variant_visitor
- {
- Fun fun_;
- Variant * var_;
-
- // clang-format off
- template<typename U, std::size_t N>
- auto CPP_auto_fun(operator())(indexed_element<U, N> u)
- (
- return compose(emplace_fn<Variant, N>{var_}, fun_)(u)
- )
- // clang-format on
- };
-
- template<typename Variant, typename Fun>
- variant_visitor<Fun, Variant> make_variant_visitor(
- Variant & var,
- Fun fun) noexcept(std::is_nothrow_move_constructible<Fun>::value)
- {
- return {detail::move(fun), &var};
- }
-
- template<typename To, typename From>
- struct unique_visitor;
-
- template<typename... To, typename... From>
- struct unique_visitor<variant<To...>, variant<From...>>
- {
- variant<To...> * var_;
-
- template<typename T, std::size_t N>
- void operator()(indexed_element<T, N> t) const
- {
- using E = meta::at_c<meta::list<From...>, N>;
- static_assert(RANGES_IS_SAME(T const, E const),
- "Is indexed_element broken?");
- using F = meta::find<meta::list<To...>, E>;
- static constexpr std::size_t M = sizeof...(To) - F::size();
- compose(emplace_fn<variant<To...>, M>{var_}, get_datum_fn{})(t);
- }
- };
-
- template<typename T>
- constexpr T & variant_deref_(T * t) noexcept
- {
- return *t;
- }
- inline void variant_deref_(void const volatile *) noexcept
- {}
-
- template<typename Variant>
- struct variant_get
- {
- ////////////////////////////////////////////////////////////////////////////////////////////
- // get
- template<std::size_t N>
- friend meta::_t<
- std::add_lvalue_reference<meta::at_c<meta::as_list<Variant>, N>>>
- get(Variant & var)
- {
- using elem_t = meta::_t<
- std::remove_reference<meta::at_c<meta::as_list<Variant>, N>>>;
- elem_t * elem = nullptr;
- auto & data_var = detail::variant_core_access::data(var);
- detail::variant_visit_(
- var.index(), data_var, detail::get_fn<elem_t, N>{&elem});
- return detail::variant_deref_(elem);
- }
- template<std::size_t N>
- friend meta::_t<
- std::add_lvalue_reference<meta::at_c<meta::as_list<Variant>, N> const>>
- get(Variant const & var)
- {
- using elem_t = meta::_t<
- std::remove_reference<meta::at_c<meta::as_list<Variant>, N> const>>;
- elem_t * elem = nullptr;
- auto & data_var = detail::variant_core_access::data(var);
- detail::variant_visit_(
- var.index(), data_var, detail::get_fn<elem_t, N>{&elem});
- return detail::variant_deref_(elem);
- }
- template<std::size_t N>
- friend meta::_t<
- std::add_rvalue_reference<meta::at_c<meta::as_list<Variant>, N>>>
- get(Variant && var)
- {
- using elem_t = meta::_t<
- std::remove_reference<meta::at_c<meta::as_list<Variant>, N>>>;
- elem_t * elem = nullptr;
- auto & data_var = detail::variant_core_access::data(var);
- detail::variant_visit_(
- var.index(), data_var, detail::get_fn<elem_t, N>{&elem});
- using res_t = meta::_t<
- std::add_rvalue_reference<meta::at_c<meta::as_list<Variant>, N>>>;
- return static_cast<res_t>(detail::variant_deref_(elem));
- }
- };
-
- template<typename Variant,
- bool Trivial = std::is_trivially_destructible<meta::apply<
- meta::quote<variant_data>, meta::as_list<Variant>>>::value>
- struct variant_base : variant_get<Variant>
- {
- ~variant_base()
- {
- static_cast<Variant *>(this)->clear_();
- }
- };
- template<typename... Ts>
- struct variant_base<variant<Ts...>, true> : variant_get<variant<Ts...>>
- {};
-
- template<typename Fun, typename Types, typename Indices, typename = void>
- struct variant_visit_results
- {};
- template<typename Fun, typename... Ts, std::size_t... Is>
- struct variant_visit_results<
- Fun, meta::list<Ts...>, meta::index_sequence<Is...>,
- meta::void_<invoke_result_t<Fun &, indexed_element<Ts, Is>>...>>
- {
- using type = variant<invoke_result_t<Fun &, indexed_element<Ts, Is>>...>;
- };
- template<typename Fun, typename... Ts>
- using variant_visit_results_t =
- meta::_t<variant_visit_results<Fun, meta::list<Ts...>,
- meta::make_index_sequence<sizeof...(Ts)>>>;
- } // namespace detail
- /// \endcond
-
- /// \addtogroup group-utility
- /// @{
- template<typename... Ts>
- struct variant
- : private detail::variant_data<Ts...>
- , private detail::variant_base<variant<Ts...>>
- {
- private:
- friend detail::variant_core_access;
- template<typename...>
- friend struct variant;
- friend detail::variant_base<variant, false>;
- template<std::size_t Index>
- using datum_t = detail::variant_datum_t<Index, Ts...>;
- template<typename T>
- using add_const_t = meta::if_<std::is_void<T>, void, T const>;
- using unbox_fn = detail::get_datum_fn;
-
- detail::variant_data<Ts...> & data_() & noexcept
- {
- return *this;
- }
- detail::variant_data<Ts...> const & data_() const & noexcept
- {
- return *this;
- }
- detail::variant_data<Ts...> && data_() && noexcept
- {
- return static_cast<detail::variant_data<Ts...> &&>(*this);
- }
-
- std::size_t index_;
-
- void clear_() noexcept
- {
- if(valid())
- {
- detail::variant_visit_(index_, data_(), detail::delete_fn{}, identity{});
- index_ = (std::size_t)-1;
- }
- }
- template<typename That>
- void assign_(That && that)
- {
- if(that.valid())
- index_ = detail::variant_move_copy_(
- that.index_, data_(), ((That &&) that).data_());
- }
- constexpr variant(detail::empty_variant_tag) noexcept
- : detail::variant_data<Ts...>{}
- , index_((std::size_t)-1)
- {}
- template<typename... Args>
- static constexpr auto all_convertible_to(int) noexcept -> CPP_ret(bool)( //
- requires(sizeof...(Args) == sizeof...(Ts)))
- {
- return and_v<convertible_to<Args, Ts>...>;
- }
- template<typename... Args>
- static constexpr bool all_convertible_to(long) noexcept
- {
- return false;
- }
-
- public:
- CPP_member
- constexpr CPP_ctor(variant)()( //
- noexcept(std::is_nothrow_default_constructible<datum_t<0>>::value) //
- requires default_constructible<datum_t<0>>)
- : variant{emplaced_index<0>}
- {}
- CPP_template(std::size_t N, typename... Args)( //
- requires constructible_from<datum_t<N>, Args...>) //
- constexpr variant(RANGES_EMPLACED_INDEX_T(N), Args &&... args) noexcept(
- std::is_nothrow_constructible<datum_t<N>, Args...>::value)
- : detail::variant_data<Ts...>{meta::size_t<N>{}, static_cast<Args &&>(args)...}
- , index_(N)
- {}
- CPP_template(std::size_t N, typename T, typename... Args)( //
- requires constructible_from<datum_t<N>, std::initializer_list<T> &,
- Args...>) //
- constexpr variant(
- RANGES_EMPLACED_INDEX_T(N), std::initializer_list<T> il,
- Args &&... args) noexcept(std::
- is_nothrow_constructible<
- datum_t<N>, std::initializer_list<T> &,
- Args...>::value)
- : detail::variant_data<Ts...>{meta::size_t<N>{},
- il,
- static_cast<Args &&>(args)...}
- , index_(N)
- {}
- template<std::size_t N>
- constexpr CPP_ctor(variant)(RANGES_EMPLACED_INDEX_T(N), meta::nil_)( //
- noexcept(std::is_nothrow_constructible<datum_t<N>, meta::nil_>::value) //
- requires constructible_from<datum_t<N>, meta::nil_>)
- : detail::variant_data<Ts...>{meta::size_t<N>{}, meta::nil_{}}
- , index_(N)
- {}
- variant(variant && that)
- : detail::variant_data<Ts...>{}
- , index_(detail::variant_move_copy_(that.index(), data_(),
- std::move(that.data_())))
- {}
- variant(variant const & that)
- : detail::variant_data<Ts...>{}
- , index_(detail::variant_move_copy_(that.index(), data_(), that.data_()))
- {}
- template<typename... Args>
- CPP_ctor(variant)(variant<Args...> that)( //
- requires(!same_as<variant<Args...>, variant>) &&
- (all_convertible_to<Args...>(0)))
- : detail::variant_data<Ts...>{}
- , index_(detail::variant_move_copy_(that.index(), data_(),
- std::move(that.data_())))
- {}
- variant & operator=(variant && that)
- {
- // TODO do a simple move assign when index()==that.index()
- this->clear_();
- this->assign_(detail::move(that));
- return *this;
- }
- variant & operator=(variant const & that)
- {
- // TODO do a simple copy assign when index()==that.index()
- this->clear_();
- this->assign_(that);
- return *this;
- }
- template<typename... Args>
- auto operator=(variant<Args...> that) -> CPP_ret(variant &)( //
- requires(!same_as<variant<Args...>, variant>) &&
- (all_convertible_to<Args...>(0)))
- {
- // TODO do a simple copy assign when index()==that.index()
- this->clear_();
- this->assign_(that);
- return *this;
- }
- static constexpr std::size_t size() noexcept
- {
- return sizeof...(Ts);
- }
- template<std::size_t N, typename... Args>
- auto emplace(Args &&... args) -> CPP_ret(void)( //
- requires constructible_from<datum_t<N>, Args...>)
- {
- this->clear_();
- detail::construct_fn<N, Args &&...> fn{static_cast<Args &&>(args)...};
- detail::variant_visit_(N, data_(), std::ref(fn), identity{});
- index_ = N;
- }
- constexpr bool valid() const noexcept
- {
- return index() != (std::size_t)-1;
- }
- constexpr std::size_t index() const noexcept
- {
- return index_;
- }
- template<typename Fun>
- detail::variant_visit_results_t<composed<Fun, unbox_fn>, Ts...> visit(Fun fun)
- {
- detail::variant_visit_results_t<composed<Fun, unbox_fn>, Ts...> res{
- detail::empty_variant_tag{}};
- detail::variant_visit_(index_,
- data_(),
- detail::make_variant_visitor(
- res, compose(detail::move(fun), unbox_fn{})));
- return res;
- }
- template<typename Fun>
- detail::variant_visit_results_t<composed<Fun, unbox_fn>, add_const_t<Ts>...>
- visit(Fun fun) const
- {
- detail::variant_visit_results_t<composed<Fun, unbox_fn>, add_const_t<Ts>...>
- res{detail::empty_variant_tag{}};
- detail::variant_visit_(index_,
- data_(),
- detail::make_variant_visitor(
- res, compose(detail::move(fun), unbox_fn{})));
- return res;
- }
- template<typename Fun>
- detail::variant_visit_results_t<Fun, Ts...> visit_i(Fun fun)
- {
- detail::variant_visit_results_t<Fun, Ts...> res{detail::empty_variant_tag{}};
- detail::variant_visit_(
- index_, data_(), detail::make_variant_visitor(res, detail::move(fun)));
- return res;
- }
- template<typename Fun>
- detail::variant_visit_results_t<Fun, add_const_t<Ts>...> visit_i(Fun fun) const
- {
- detail::variant_visit_results_t<Fun, add_const_t<Ts>...> res{
- detail::empty_variant_tag{}};
- detail::variant_visit_(
- index_, data_(), detail::make_variant_visitor(res, detail::move(fun)));
- return res;
- }
- };
-
- template<typename... Ts, typename... Us>
- auto operator==(variant<Ts...> const & lhs, variant<Us...> const & rhs)
- -> CPP_ret(bool)( //
- requires and_v<equality_comparable_with<Ts, Us>...>)
- {
- return (!lhs.valid() && !rhs.valid()) ||
- (lhs.index() == rhs.index() &&
- detail::variant_equal_(lhs.index(),
- detail::variant_core_access::data(lhs),
- detail::variant_core_access::data(rhs)));
- }
-
- template<typename... Ts, typename... Us>
- auto operator!=(variant<Ts...> const & lhs, variant<Us...> const & rhs)
- -> CPP_ret(bool)( //
- requires and_v<equality_comparable_with<Ts, Us>...>)
- {
- return !(lhs == rhs);
- }
-
- ////////////////////////////////////////////////////////////////////////////////////////////
- // emplace
- template<std::size_t N, typename... Ts, typename... Args>
- meta::if_c<(bool)constructible_from<detail::variant_datum_t<N, Ts...>, Args...>>
- emplace(variant<Ts...> & var, Args &&... args)
- {
- var.template emplace<N>(static_cast<Args &&>(args)...);
- }
-
- ////////////////////////////////////////////////////////////////////////////////////////////
- // variant_unique
- template<typename Var>
- struct variant_unique
- {};
-
- template<typename... Ts>
- struct variant_unique<variant<Ts...>>
- {
- using type = meta::apply<meta::quote<variant>, meta::unique<meta::list<Ts...>>>;
- };
-
- template<typename Var>
- using variant_unique_t = meta::_t<variant_unique<Var>>;
-
- ////////////////////////////////////////////////////////////////////////////////////////////
- // unique_variant
- template<typename... Ts>
- variant_unique_t<variant<Ts...>> unique_variant(variant<Ts...> const & var)
- {
- using From = variant<Ts...>;
- using To = variant_unique_t<From>;
- auto res = detail::variant_core_access::make_empty(meta::id<To>{});
- var.visit_i(detail::unique_visitor<To, From>{&res});
- RANGES_EXPECT(res.valid());
- return res;
- }
- /// @}
- } // namespace ranges
-
- RANGES_DIAGNOSTIC_PUSH
- RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
-
- namespace std
- {
- template<typename... Ts>
- struct tuple_size<::ranges::variant<Ts...>> : tuple_size<tuple<Ts...>>
- {};
-
- template<size_t I, typename... Ts>
- struct tuple_element<I, ::ranges::variant<Ts...>> : tuple_element<I, tuple<Ts...>>
- {};
- } // namespace std
-
- RANGES_DIAGNOSTIC_POP
-
- #endif
|