5#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_VARIANT_VISIT_HPP_
6#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_VARIANT_VISIT_HPP_
12#include "arene/base/contracts/contract.hpp"
13#include "arene/base/functional/invoke.hpp"
14#include "arene/base/stdlib_choice/cstddef.hpp"
15#include "arene/base/stdlib_choice/decay.hpp"
16#include "arene/base/stdlib_choice/declval.hpp"
17#include "arene/base/stdlib_choice/forward.hpp"
18#include "arene/base/stdlib_choice/ignore.hpp"
19#include "arene/base/stdlib_choice/integer_sequence.hpp"
20#include "arene/base/stdlib_choice/is_constructible.hpp"
21#include "arene/base/stdlib_choice/is_same.hpp"
22#include "arene/base/type_traits/all_of.hpp"
23#include "arene/base/type_traits/is_invocable.hpp"
24#include "arene/base/variant/traits.hpp"
25#include "arene/base/variant/variant.hpp"
31namespace visit_detail {
38template <
typename VisitorRefT,
typename VariantRefT, std::size_t Idx>
39using visitor_invoke_result_at_t =
40 invoke_result_t<VisitorRefT,
decltype(::arene::base::get<Idx>(std::declval<VariantRefT>()))>;
48template <
typename VisitorRefT,
typename VariantRefT>
49using visitor_invoke_result_t = visitor_invoke_result_at_t<VisitorRefT, VariantRefT, 0U>;
59 typename Indexes = std::make_index_sequence<::arene::base::variant_size_v<std::decay_t<VariantRefT>>>>
60class are_visitor_returns_the_same_type;
67template <
typename VisitorRefT,
typename VariantRefT>
68class are_visitor_returns_the_same_type<VisitorRefT, VariantRefT, std::index_sequence<>> {};
75template <
typename VisitorRefT,
typename VariantRefT, std::size_t Idx, std::size_t... Idxs>
76class are_visitor_returns_the_same_type<VisitorRefT, VariantRefT, std::index_sequence<Idx, Idxs...>>
77 : are_visitor_returns_the_same_type<VisitorRefT, VariantRefT, std::index_sequence<Idxs...>> {
80 visitor_invoke_result_t<VisitorRefT, VariantRefT>,
81 visitor_invoke_result_at_t<VisitorRefT, VariantRefT, Idx>>::value,
82 "visit requires all visitor overloads to return exactly the same type."
95template <
typename Ret,
typename VisitorRefT,
typename VariantRefT, std::size_t Idx>
96constexpr bool is_visitor_nothrow_invocable_r_at_v =
97 is_nothrow_invocable_r_v<Ret, VisitorRefT,
decltype(::arene::base::get<Idx>(std::declval<VariantRefT>()))> &&
98 std::is_nothrow_constructible<Ret, visitor_invoke_result_at_t<VisitorRefT, VariantRefT, Idx>>::value;
109 typename VisitorRefT,
110 typename VariantRefT,
111 typename Indexes = std::make_index_sequence<::arene::base::variant_size_v<std::decay_t<VariantRefT>>>>
112constexpr bool is_visitor_nothrow_invocable_r_v{
false};
121template <
typename Ret,
typename VisitorRefT,
typename VariantRefT, std::size_t... Idxs>
122constexpr bool is_visitor_nothrow_invocable_r_v<
126 std::index_sequence<Idxs...>>{::arene::base::all_of_v<
127 is_visitor_nothrow_invocable_r_at_v<Ret, VisitorRefT, VariantRefT, Idxs>...>};
135 typename VisitorRefT,
136 typename VariantRefT,
137 typename RetT = visitor_invoke_result_t<VisitorRefT, VariantRefT>,
138 typename Indexes = std::make_index_sequence<::arene::base::variant_size_v<std::decay_t<VariantRefT>>>>
139class visit_dispatcher;
146template <
typename VisitorRefT,
typename VariantRefT,
typename RetT, std::size_t... Idxs>
147class visit_dispatcher<VisitorRefT, VariantRefT, RetT, std::index_sequence<Idxs...>> {
158 template <std::size_t Idx>
159 static constexpr auto invoke_visitor(
162 )
noexcept(is_visitor_nothrow_invocable_r_at_v<RetT, VisitorRefT, VariantRefT, Idx>) -> RetT {
163 return ::arene::base::invoke(
164 static_cast<VisitorRefT>(visitor),
165 ::arene::base::get<Idx>(
static_cast<VariantRefT>(vrnt))
173 using invoke_visitor_fn_t = RetT (*)(VisitorRefT visitor, VariantRefT vrnt);
176 using jump_table_t = invoke_visitor_fn_t[::arene::base::variant_size_v<std::decay_t<VariantRefT>>];
180 static constexpr jump_table_t visitor_fns{invoke_visitor<Idxs>...};
193 constexpr auto operator()(VisitorRefT visitor, VariantRefT vrnt)
const
194 noexcept(is_visitor_nothrow_invocable_r_v<RetT, VisitorRefT, VariantRefT>) -> RetT {
195 return visitor_fns[vrnt.index()](
static_cast<VisitorRefT>(visitor),
static_cast<VariantRefT>(vrnt));
202template <
typename VisitorRefT,
typename VariantRefT,
typename RetT, std::size_t... Idxs>
203constexpr typename visit_dispatcher<VisitorRefT, VariantRefT, RetT, std::index_sequence<Idxs...>>::jump_table_t
204 visit_dispatcher<VisitorRefT, VariantRefT, RetT, std::index_sequence<Idxs...>>::visitor_fns;
218template <
typename VisitorT,
typename VariantT>
228 std::ignore = visit_detail::are_visitor_returns_the_same_type<
decltype(visitor),
decltype(vrnt)>{};
229 ARENE_PRECONDITION(!vrnt.valueless_by_exception());
230 return visit_detail::visit_dispatcher<
decltype(visitor),
decltype(vrnt)>{
231 }(std::forward<VisitorT>(visitor), std::forward<VariantT>(vrnt));
247template <
typename RetT,
typename VisitorT,
typename VariantT>
252 ARENE_PRECONDITION(!vrnt.valueless_by_exception());
253 return visit_detail::visit_dispatcher<
decltype(visitor),
decltype(vrnt), RetT>{
254 }(std::forward<VisitorT>(visitor), std::forward<VariantT>(vrnt));
Definition array_exceptions_disabled.cpp:11
auto visit(VisitorT &&visitor, VariantT &&vrnt) noexcept(visit_detail::is_visitor_nothrow_invocable_r_v< visit_detail::visitor_invoke_result_t<, >,, >) -> visit_detail::visitor_invoke_result_t<, >
Invokes a given visitor with the active alternative in a given variant.
Definition visit.hpp:219
auto visit(VisitorT &&visitor, VariantT &&vrnt) noexcept(visit_detail::is_visitor_nothrow_invocable_r_v< RetT,, >) -> RetT
Invokes a given visitor with the active alternative in a given variant.
Definition visit.hpp:248
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10