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?
>Solution :
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.