我正在用C ++ 11学习可变参数模板。如何调用test.finder作为test.var_finder的功能参数?
#include <functional>
#include <iostream>
class c_test {
public:
double finder(double a, double b = 0) {
return a + b;
};
template<typename... Args>
double var_finder(double c, Args... args, std::function<double (Args... args)> func) {
return c * func(args...);
};
};
int main () {
c_test test;
std::cout << test.var_finder(0.1, 2, test.finder) << std::endl;
return 0;
}
我的预期结果是0.1 *(2 + 0)= 0.2。
这里有很多事情要处理。
首先,将参数包args
放在最后,否则编译器将不知道从何处停止匹配参数(除非您指定模板参数)。
template<typename... Args>
double var_finder(double c, std::function<double (Args... args)> func, Args... args)
第二,不要在std::function
中命名参数;也只是不使用std::function
,而是使用函数指针。
template<typename... Args>
double var_finder(double c, double (*func)(Args...), Args... args)
第三,将finder
设为静态,否则会遇到成员函数指针,并且语法更难掌握。
static double finder(double a, double b = 0)
第三,为finder
提供可选参数。否则,无法推导出参数包,因为它与func
和args
都不匹配。
std::cout << test.var_finder(0.1, c_test::finder, 2.0, 0.0) << std::endl;
这将为您提供以下内容。
class c_test {
public:
static double finder(double a, double b = 0) {
return a + b;
}
template<typename... Args>
double var_finder(double c, double (*func)(Args...), Args... args) {
return c * func(args...);
}
};
int main () {
c_test test;
std::cout << test.var_finder(0.1, c_test::finder, 2.0, 0.0) << std::endl;
}
您的解决方案有很多问题:
1]您不能将成员函数转换为std::function
,因为没有对象就无法调用成员函数。您可以通过使成员函数为static
或使用std::bind
或使用lambda来解决此问题。
2)在方法参数中间不能有可变参数列表。可变参数必须转到参数列表的末尾。
3)您不能在参数列表本身内部“动态”推断模板参数。解决方案:将新的模板参数与默认模板参数一起使用。
4)我看不出要在std :: function中使用的函数带有默认参数的机会,该函数会返回不同的签名double(double)
与double(double,double)
class c_test {
public:
static double finders(double a, double b = 0) {
return a + b;
};
double finder(double a, double b = 0) {
return a + b;
};
template<typename... Args, typename F= std::function<double(Args...)> >
double var_finder(double c, F func, Args... args) {
return c * func(args...);
}
};
int main () {
c_test test;
// use static member
std::cout << test.var_finder(0.1, test.finders, 2.,3.) << std::endl;
// use lambda instead of all the hacky things
std::cout << test.var_finder(0.1, [&test](double p1,double p2){ return test.finder(p1,p2); }, 2.,3.) << std::endl;
return 0;
}
我发现使用lambdas的可能性:
std::cout << test.var_finder<c_test, double> (0.1, test, 2, [] (c_test test_, double a_) { return test_.finder(a_); } ) << std::endl;
还有其他(不太麻烦的)可能性吗?