user2609733 user2609733 - 1 month ago 11
C++ Question

Variadic templates, recursion, non-typename parameters

Am trying to build some simple variadic template with non-typename parameters:

#include <iostream>

void myf()
{
}

template<int Arg1, int ... Args> void myf()
{
std::cout << Arg1 << ", ";
myf<Args...>();
}

int main()
{
myf<1,2,3,4,5>();
}


Trying to compile this and got:

test.cpp: In instantiation of ‘void myf() [with int Arg1 = 5; int ...Args = {}]’:
test.cpp:10:18: recursively required from ‘void myf() [with int Arg1 = 2; int ...Args = {3, 4, 5}]’
test.cpp:10:18: required from ‘void myf() [with int Arg1 = 1; int ...Args = {2, 3, 4, 5}]’
test.cpp:15:20: required from here
test.cpp:10:18: error: no matching function for call to ‘myf()’
myf<Args...>();
^
test.cpp:10:18: note: candidate is:
test.cpp:7:39: note: template<int Arg1, int ...Args> void myf()
template<int Arg1, int ... Args> void myf()
^
test.cpp:7:39: note: template argument deduction/substitution failed:
test.cpp:10:18: note: couldn't deduce template parameter ‘Arg1’
myf<Args...>();


It seems, recursion termination not working. What is the correct way to terminate non-typename variadic template recursion?

Answer

The correct solution would be to have the last case as the one parameter case instead of the no parameter case. The problem is that your last call expands to this:

myf<>();

Which is not quite valid.

Instead, you might want to do this:

// one parameter case:
template<int Arg>
void myf()
{
    std::cout << Arg << std::endl;
}

// two or more parameters:
template<int Arg1, int Arg2, int... Args>
void myf()
{
   std::cout << Arg1 << ", " << Arg2 << ", ";
   myf<Args...>();
}

Here's a live example at Coliru