.
Hi :-)
I have the following code : the goal is to return a function that is the sum of other functions, roughly. And to learn about variadic templates.
#include <iostream>
template <typename F>
struct FSum {
FSum(F f) : f_(f) {} ;
int operator()() {
return f_() ;
}
F f_ ;
} ;
template <typename F1, typename F2, typename... Frest>
struct FSum {
FSum(F1 f1, F2 f2, Frest... frest) {
f_ = f1 ;
frest_ = FSum<F2, Frest...>(f2, frest...) ;
}
int operator()() {
return f_() + frest_() ;
}
F1 f_ ;
FSum<F2, Frest...> frest_ ;
} ;
struct F1 {
int operator() () { return 1 ; } ;
} ;
struct F2 {
int operator() () { return 2 ; } ;
} ;
struct F3 {
int operator() () { return 3 ; } ;
} ;
int main() {
F1 f1 ;
F2 f2 ;
F3 f3 ;
FSum<F1, F2, F3> fsum = FSum<F1, F2, F3>(f1, f2, f3) ;
std::cout << fsum() << std::endl ;
}
But I got the following error message from clang (g++ also gives an error) :
test_variadic.cpp:14:1: error: too many template parameters in template redeclaration template ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
And well I don't understand. I though the compiler would choose the class depending on the number of template parameters ? Since the first one has exactly one and the other one has 2 or more.
Any idea ?
Thanks a lot :-)
The compiler is complaining because you are redeclaring the same template struct twice, and what you need is Partial Template Specialization. See the syntax in the example below.
As for the logic to get the variadic template to do what you want, it helps to think of it in terms of recursion. The following code does what you want:
#include <iostream>
using namespace std;
// stops "recursion" when it is called with no parameters
template <typename... Frest> struct FSum {
int operator()() {
return 0;
}
};
// Partial Specialization of FSum above
// called when there is at least one template parameter
template <typename F, typename... Frest>
struct FSum<F, Frest...> {
// "recursion" in the construction of frest_
FSum(F f, Frest... frest) : f_(f), frest_(frest...) {}
// "recursion" in the calling of frest()
int operator()() {
return f_() + frest_();
}
F f_;
FSum<Frest...> frest_;
};
struct F1 {
int operator()() { return 1; }
};
struct F2 {
int operator()() { return 2; }
};
struct F3 {
int operator()() { return 3; }
};
int main() {
F1 f1;
F2 f2;
F3 f3;
FSum<F1, F2, F3> fsum(f1, f2, f3);
cout << fsum() << endl;
}
Note that I use the word "recursion," but as I understand it, there is no recursion. Instead, there is a sequence of function calls generated at compile time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With