This is what I\'m trying to do:
// base case
void f() {}
template
void f() {
Another way is turning the non-template function f
into a variadic template function which accepts zero or more template arguments (the other f
requires one or more template arguments). Then to avoid ambiguity, SFINAE away this template function when the number of arguments is not zero. Well, a code is better than 1000 words:
#include <type_traits>
template <typename... Ts>
typename std::enable_if<sizeof...(Ts) == 0>::type f() {
}
template <typename T, typename... Ts>
void f() {
// do something with T
f<Ts...>();
}
Since c++20 you can use constraints to functions, instead of SFINAE.
template <typename... Ts>
requires (sizeof...(Ts) == 0)
void f(){}
template <typename T, typename... Ts>
void f() {
// do something with T
f<Ts...>();
}
Since class templates can be partially specialized, another possibility is to use class templates to do the work, and have your function delegate to them:
template<typename... Ts>
struct caller
{
static void call() { } // Base case, terminates recursion
};
template<typename T, typename... Ts>
struct caller<T, Ts...>
{
static void call()
{
// Do something with T
caller<Ts...>::call();
}
};
template<typename... Ts>
void f() {
caller<Ts...>::call();
}