I have a generic class Test<T>
and I want to have a function test_function()
that has a variable number of Test<T>
object input parameters with ...
. In the function, I want to iterate over all the parameters. The generic type T
can be different across the parameters. Something like this:
template <typename T> class Test {
private:
T value = (T)0;
int test = 1;
public:
Test() = default;
int get_test() {
return test;
}
}
template <typename T> void test_function(const Test<T> tests...) {
for(auto test : tests) {
cout << test.get_test() << endl;
}
}
When compiling, I get the errors:
error C3520: "T": Parameter pack must be extended in this context
error C3520: "tests": Parameter pack must be extended in this context
error C3312: no callable 'begin' function found for type 'unknown-type'
error C3312: no callable 'end' function found for type 'unknown-type'
What am I doing wrong?
EDIT: Is it possible to have a counter in the expansion?
EDIT 2: I figured it out with the counter:
template <typename ...T> void test_function(const Test<T> ...tests) {
int i=0;
((cout << tests.get_test() << ", counter = " << i++ << endl), ...);
}
There are multiple problems here.
First, the correct variadic template function declaration should be:
template <typename ...T> void test_function(const Test<T> ...tests)
But that won't solve all the problems. The first one is that all the parameters are const
objects, therefore the class method must also be a const class member:
int get_test() const {
Finally:
for(auto test : tests) {
tests
is not a container that can be range-iterated over, like a vector. It is a parameter pack and needs to be expanded like one:
((cout << tests.get_test()), ...);
Tested with gcc 11:
#include <iostream>
using namespace std;
template <typename T> class Test {
private:
T value = (T)0;
int test = 1;
public:
Test() = default;
int get_test() const {
return test;
}
};
template <typename ...T> void test_function(const Test<T> ...tests) {
((cout << tests.get_test()), ...);
}
void foo()
{
test_function(Test<int>{}, Test<char>{});
}