types/tagged: add 'visit' call
This commit is contained in:
parent
c9b5605213
commit
4a556af89d
@ -134,4 +134,71 @@ namespace cruft {
|
||||
cruft::max (sizeof (ValueT)...)
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
namespace detail {
|
||||
// If the tagged object matches the IndexV'th type in ComponentsT then
|
||||
// invoke visitor with the object as the argument. Else, advance to
|
||||
// the next index and try with that type.
|
||||
//
|
||||
// We assume that outside callers only call this function with an
|
||||
// IndexV of 0 (so that we have assurances that every type is visited).
|
||||
template <
|
||||
std::size_t IndexV,
|
||||
typename VisitorT,
|
||||
template <typename...> typename TaggedT,
|
||||
typename ...ComponentsT
|
||||
>
|
||||
requires std::is_same_v<
|
||||
std::remove_cvref_t<TaggedT<ComponentsT...>>,
|
||||
tagged<ComponentsT...>
|
||||
>
|
||||
decltype (auto)
|
||||
visit (
|
||||
VisitorT &&visitor,
|
||||
TaggedT<ComponentsT...> arg
|
||||
) {
|
||||
static_assert (IndexV < sizeof...(ComponentsT));
|
||||
using nth_t = std::tuple_element_t<IndexV, std::tuple<ComponentsT...>>;
|
||||
|
||||
// If we're the last valid index then we must be invoked because
|
||||
// there's no other option. Do this, and (statically) avoid
|
||||
// further recursion.
|
||||
if constexpr (IndexV + 1 == sizeof...(ComponentsT)) {
|
||||
return std::invoke (visitor, arg.template get<nth_t> ());
|
||||
} else {
|
||||
// If the tag matches, then dispatch, else recurse with the
|
||||
// next available type index.
|
||||
if (arg.tag () == nth_t::tag) {
|
||||
return std::invoke (visitor, arg.template get<nth_t> ());
|
||||
} else {
|
||||
return visit<IndexV+1> (
|
||||
std::forward<VisitorT> (visitor),
|
||||
arg
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <
|
||||
typename VisitorT,
|
||||
template <typename...> typename TaggedT,
|
||||
typename ...ComponentsT
|
||||
>
|
||||
requires std::is_same_v<
|
||||
std::remove_cvref_t<TaggedT<ComponentsT...>>,
|
||||
tagged<ComponentsT...>
|
||||
>
|
||||
decltype (auto)
|
||||
visit (VisitorT &&visitor, TaggedT<ComponentsT...> arg)
|
||||
{
|
||||
static_assert (sizeof...(ComponentsT));
|
||||
|
||||
return detail::visit<0> (
|
||||
std::forward<VisitorT> (visitor),
|
||||
arg
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user