我有以下C ++ 11示例,其中我有一个call
函数,它使用可变参数模板来接受和调用泛型类方法:
#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;
}
如代码中所述,我在函数接受int
时无法传递const int
,而在方向调用中我无法传递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);
^
。我得到以下编译错误:
{{1}}
与常规执行相比,C ++可变参数模板是否会强制执行更严格的类型检查?我使用g ++ 4.8.1和C ++ 11。
答案 0 :(得分:14)
您调用功能模板的方式,模板参数包Args
将从两个来源推断出来:
int (Calculator::*)(const int&, const int&)
*a, *b)
- int &, int &
如果推算成功,推断的结果必须完全匹配。他们显然不会。
对于可变参数模板,这不是新的或特殊的。如果您尝试执行std::max(1, 1.5)
,则会遇到同样的问题 - 编译器从一个参数中推导出int
,从另一个参数中推导出double
,并且因为两个参数冲突而导致推论失败。
最简单的修复可能需要两包:
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)...);
}