I have the following C++11 example where I have a call
function that uses variadic templates to accept and call a generic class method:
#include <utility>
template <typename T, typename R, typename... Args>
R call(R (T::*fn)(Args...), T *t, Args&&... args) {
return ((*t).*fn)(std::forward<Args>(args)...);
}
class Calculator {
public:
int add(const int& a, const int& b) {
return a + b;
}
};
int main() {
Calculator *calculator = new Calculator();
int* a = new int(2);
int* b = new int(4);
// compiles
int res1 = calculator->add(*a, *b);
// does not compile!
int res2 = call<Calculator>(&Calculator::add,calculator, *a, *b);
return 0;
}
As commented in the code, I'm not able to pass an int
when the function accept const int
, while in the direction method call I can. I get the following compile error:
error: no matching function for call to ‘call(int (Calculator::*)(const int&, const int&), Calculator*&, int&, int&)’
int res2 = call<Calculator>(&Calculator::add,calculator, *a, *b);
^
inconsistent parameter pack deduction with ‘const int&’ and ‘int&’
int res2 = call<Calculator>(&Calculator::add,calculator, *a, *b);
^
Does the C++ variadic template enforce stricter type checking when compared to regular execution? I'm using g++ 4.8.1 with C++ 11.
The way you are calling your function template, the template parameter pack Args
will be deduced from two sources:
int (Calculator::*)(const int&, const int&)
*a, *b)
you passed for the function parameter pack - int &, int &
For deduction to succeed, the result deduced must exactly match. They obviously don't.
This isn't new or special to variadic templates. You have the same issue if you try to do std::max(1, 1.5)
- the compiler deduces int
from one argument, double
from the other, and deduction fails because the two conflict.
Simplest fix is probably taking two packs:
template <typename T, typename R, typename... Args1, typename... Args2>
R call(R (T::*fn)(Args1...), T *t, Args2&&... args) {
return ((*t).*fn)(std::forward<Args2>(args)...);
}
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