0

Consider the following template recursion function. Its purpose is to create a vector containing all values in the enum class EnumClassName for which its associated predicate function bool xxx<N>() returns true.

template <EnumClassName N = EnumClassName::LAST_ENUM_VALUE> 
std::vector<EnumClassName> xxx_stuff()
{
    std::vector<EnumClassName> v = xxx_stuff<EnumClassName(static_cast<int>(N) - 1)>();

    if (xxx<N>()) {
        v.emplace_back(N);
    }
    return v;
}

with the recursion base case:

template <> std::vector<EnumClassName> xxx_stuff<EnumClassName::FIRST_ENUM_VALUE>()
{
    return {};
}

Now assume there are 10 of these functions where the only thing that differs is the xxx name. I.e. we have the functions alpha_stuff with a corresponding predicate function alpha<N>, beta_stuff with a corresponding predicate function beta<N>, etc etc.

Is there any way to not duplicate the above function 10 times, where the only difference is the replacement of xxx with alpha, beta etc in each duplicate?

I am not able to just loop over the enum values, because the xxx<N> functions in turn call another function yyy<N> which will not accept a runtime-generated template argument <N> (forgive my lingo there, I actually have no idea what I'm talking about or how this works, I just know it gave me compilation errors when I tried it that way).

Daniel
  • 1

1 Answers1

0

You cannot pass function template as argument or overloaded function, but you can wrap the call in a type, and then

template <typename EnumClassName,
          EnumClassName N = EnumClassName::LAST_ENUM_VALUE,
          typename F> 
std::vector<EnumClassName> xxx_stuff(F&& f)
{
    std::vector<EnumClassName> v =
        xxx_stuff<EnumClassName, EnumClassName(static_cast<int>(N) - 1)>(f);

    if (f(std::integral_constant<EnumClassName, N>{})) {
        v.emplace_back(N);
    }
    return v;

}

with usage

auto v = xxx_stuff<E>([](auto n) { return xxx<n()>(); });

Demo

Note: That recursion can be avoided using std::integer_sequence.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • Thank you! Very nice solution! Although what really helped me was the reference `std::integer_sequence` which I ended up using instead, and avoided the recursion!! Awesome. – Daniel Feb 16 '22 at 04:01