Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How best to write the base case of this recursive template?

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?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading