I'm trying to write a template function that has this behavior:
// count_template_params<>() == 0
// count_template_params<int>() == 1
// count_template_params<int, int>() == 2
// count_template_params<int, int, int>() == 3
// etc...
This is the closest I've been able to achieve:
#include <iostream>
template<int DUMMY>
constexpr int count_template_params() {
return 0;
}
template<int DUMMY, class T, class... SS>
constexpr int count_template_params() {
return 1 + count_template_params<DUMMY, SS...>();
}
int main(int argc, char **argv) {
int count = count_template_params<0, int, int, int, int>();
std::cout << "Count=" << count << std::endl;
}
That works, it prints '4' as expected. However, it has the ugly DUMMY parameter. If I remove the dummy parameter, the compiler mistakes the recursion base case for template specialization. Is there a way to do this that doesn't have the DUMMY parameter?
As the other answer mentions, this particular example can be solved with sizeof...()
In fact, it cannot be solved with recursion because you are using a function template which does not allow for partial specialization.
There are, however, still many times when recursion is the best solution for working with meta-programming and templates (e.g. see this answer). The canonical approach for your particular example would be something like the following using struct
which allows for the necessary partial specialization.
#include <type_traits>
template<class... Ts>
struct count;
template<>
struct count<> {
static constexpr auto value = 0;
};
template<class T, class... Ts>
struct count<T, Ts...> {
static constexpr auto value = 1 + count<Ts...>::value;
};
template<class... Ts>
inline constexpr auto count_v = count<Ts...>::value;
static_assert(count_v<> == 0);
static_assert(count_v<int> == 1);
static_assert(count_v<int,int> == 2);
static_assert(count_v<int,int,int> == 3);
int main(int argc, const char *argv[]) {
return 0;
}
A typical maneuver is to accept template arguments as class T, class... Ts
in order to do processing on the T
and then recurse on the Ts...
as was done above.