17#if defined(__GNUC__) && __GNUC__ < 12 || defined(__clang_major__) && __clang_major__ < 15
31 template<
typename ExpectedRet>
32 struct AlternativeSelector {
34 ~AlternativeSelector() =
delete;
43 template<
size_t VisitedIndex,
size_t VariantSize,
typename Visitor,
typename Variant>
44 static constexpr ExpectedRet SelectAndInvoke(Visitor&& aVisitor, Variant&& aVariant)
46 if constexpr (VisitedIndex < VariantSize) {
48 using ActualRet =
decltype(
49 std::invoke(std::forward<Visitor>(aVisitor), std::get<VisitedIndex>(std::forward<Variant>(aVariant))));
50 static_assert(std::is_same_v<ActualRet, ExpectedRet>,
"kf::visit: visitor must have a single return type");
51 if (
auto* held = std::get_if<VisitedIndex>(&(std::forward<Variant>(aVariant)))) {
53 return std::invoke(std::forward<Visitor>(aVisitor), *held);
57 return SelectAndInvoke<VisitedIndex + 1, VariantSize>(std::forward<Visitor>(aVisitor),
58 std::forward<Variant>(aVariant));
61 __builtin_unreachable();
71 template<
typename Visitor,
typename Variant>
72 constexpr decltype(
auto) visit(Visitor&& aVisitor, Variant&& aVariant)
75 decltype(std::invoke(std::forward<Visitor>(aVisitor), std::get<0>(std::forward<Variant>(aVariant))));
76 constexpr size_t Size = std::variant_size_v<std::remove_cv_t<std::remove_reference_t<Variant>>>;
77 return detail::AlternativeSelector<ExpectedRet>::template SelectAndInvoke<0, Size>(std::forward<Visitor>(aVisitor),
78 std::forward<Variant>(aVariant));
size_t Size()
Returns the number of elements available for a given data type.