How can I pass a function template as (template) argument to a function template?

Currently, I have a code like

#include <cstdint>
#include <iostream>

template<std::uint32_t idx>
void f() {
    std::cout << "f(" << idx << ")\n";
}

template<std::uint32_t n>
void loop1() {
    f<n>();
    if constexpr (n > 0) {
        loop1<n - 1>();
    }
}

template<std::uint32_t idx>
void g() {
    std::cout << "g(" << idx << ")\n";
}

template<std::uint32_t n>
void loop2() {
    g<n>();
    if constexpr (n > 0) {
        loop2<n - 1>();
    }
}

int main() {
    loop1<4>();
    loop2<2>();
}

It’s necessary for f, g, loop1 and loop2 to be function templates. Now, I have to add more functions, but loop1 and loop2 will always be the same, a recursive template loop.

How can I pass the function template as (template) argument to loop to achieve something like:

#include <cstdint>
#include <iostream>

template<std::uint32_t idx>
void f() {
    std::cout << "f(" << idx << ")\n";
}

template<std::uint32_t idx>
void g() {
    std::cout << "g(" << idx << ")\n";
}

template<std::uint32_t n, typename h>
void loop() {
    h<n>();
    if constexpr (n > 0) {
        loop<n - 1, h>();
    }
}

int main() {
    loop<4, h>();
    loop<2, h>();
}

I prefer to pass the function as template argument at compile time, but a solution to pass the function template as function argument at runtime would also solve my problem, e.g.

#include <cstdint>
#include <iostream>

template<std::uint32_t idx>
void f() {
    std::cout << "f(" << idx << ")\n";
}

template<std::uint32_t idx>
void g() {
    std::cout << "g(" << idx << ")\n";
}

template<std::uint32_t n, typename T>
void loop(T h) {
    h<n>();
    if constexpr (n > 0) {
        loop<n - 1>(h);
    }
}

int main() {
    loop<4>(h);
    loop<2>(h);
}

or

#include <cstdint>
#include <iostream>

template<std::uint32_t idx>
void f() {
    std::cout << "f(" << idx << ")\n";
}

template<std::uint32_t idx>
void g() {
    std::cout << "g(" << idx << ")\n";
}

template<std::uint32_t n, template<std::uint32_t> typename F>
void loop(F h) {
    h<n>();
    if constexpr (n > 0) {
        loop<n - 1>(h);
    }
}

int main() {
    loop<4>(h);
    loop<2>(h);
}

Is this even possible? I know, that all of my approaches are wrong syntax. It’s just to illustrate, what I want to achieve.

>Solution :

You cannot do this with free functions but you can do something similar to what you want to have with class template static member functions:

#include <cstdint>
#include <iostream>

template<std::uint32_t idx>
struct F {
  static void function() {
    std::cout << "f(" << idx << ")\n";
  }
};

template<std::uint32_t idx>
struct G {
  static void function() {
    std::cout << "g(" << idx << ")\n";
  }
};

template<std::uint32_t n, template<std::uint32_t> typename T>
void loop() {
    T<n>::function();
    if constexpr (n > 0) {
        loop<n - 1, T>();
    }
}

int main() {
    loop<4, F>();
    loop<2, G>();
}

Here’s a demo.

Leave a Reply