CbmRoot
Loading...
Searching...
No Matches
KfVisit.h
Go to the documentation of this file.
1/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Sergei Zharko [committer] */
4
15#pragma once
16
17#if defined(__GNUC__) && __GNUC__ < 12 || defined(__clang_major__) && __clang_major__ < 15
18
19#include <functional>
20#include <type_traits>
21#include <utility>
22#include <variant>
23
24namespace cbm::algo::kf
25{
26 namespace detail
27 {
31 template<typename ExpectedRet>
32 struct AlternativeSelector {
34 ~AlternativeSelector() = delete;
35
43 template<size_t VisitedIndex, size_t VariantSize, typename Visitor, typename Variant>
44 static constexpr ExpectedRet SelectAndInvoke(Visitor&& aVisitor, Variant&& aVariant)
45 {
46 if constexpr (VisitedIndex < VariantSize) {
47 // Check, if the visited alternative is held by the variant
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)))) {
52 // This alternative is held by the variant => invoke the visitor on it
53 return std::invoke(std::forward<Visitor>(aVisitor), *held);
54 }
55 else {
56 // Try the next alternative
57 return SelectAndInvoke<VisitedIndex + 1, VariantSize>(std::forward<Visitor>(aVisitor),
58 std::forward<Variant>(aVariant));
59 }
60 }
61 __builtin_unreachable(); // No return is reachable
62 }
63 };
64 } // namespace detail
65
71 template<typename Visitor, typename Variant>
72 constexpr decltype(auto) visit(Visitor&& aVisitor, Variant&& aVariant)
73 {
74 using ExpectedRet =
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));
79 }
80} // namespace cbm::algo::kf
81
82#else // Modern compiler
83
84#include <variant>
85
86namespace cbm::algo::kf
87{
88 using std::visit; //< use a standard visit
89}
90
91#endif
size_t Size()
Returns the number of elements available for a given data type.
Definition KfUtils.h:297