我正在学习 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。
最佳答案
我猜你有点把可变参数模板部分和一些设计缺陷混在一起了
让我们开始吧。
序言:处理可变模板的正确方法是使用rvalue-reference
和std::forward
来实现 perfect forwarding .
1) 简单的方法:你根本不需要上课
您实际上并没有指代任何成员,因此类只会带来复杂性。这些情况最好引用一个免费的功能
#include <functional>
#include <iostream>
double finder(double a, double b = 0) {
return a + b;
};
template<typename Func, typename... Args>
double var_finder(double c, Func&& f, Args&&... args) {
return c * std::forward<Func>(f)(std::forward<Args>(args)...);
};
int main () {
std::cout << var_finder(0.1, finder, 2, 0) << std::endl;
return 0;
}
您的函数接受 2 个参数,因此您必须将零作为第二个参数传递。
2) 使用类
您尝试的问题是您想使用 c_test
本身的函数调用 c_test.var_finder
。现在你必须弄清楚你想要什么样的设计。你可以做出2个假设。首先是“我无论如何都想要我的类中的查找器函数”,然后你必须将它设为 static
因为它真的不使用类成员所以你不需要 c_test< 的实例
,对吧?所以使用自由函数或静态成员函数会留下 var_finder
实现,你只需要这样调用它
#include <functional>
#include <iostream>
class c_test {
public:
static double finder(double a, double b = 0) {
return a + b;
};
template<typename Func, typename... Args>
double var_finder(double c, Func&& f, Args&&... args) {
return c * std::forward<Func>(f)(std::forward<Args>(args)...);
};
};
int main () {
c_test test;
std::cout << test.var_finder(0.1, &c_test::finder, 2, 0) << std::endl;
return 0;
}
您可以做的第二个假设是“不,我希望使用 var_finder 调用任何函数成员,无论它来自哪里”。我强烈反对这种方法,因为它是从糟糕的设计中提取解决方案,因此我建议重新考虑您的设计以落入解决方案 1 或 2。
3) 奖励:一个不错的设计
您可以添加一个非可变参数函数并将用法委托(delegate)给 lambda 的使用,这允许您在其中使用成员函数而无需定义可变参数模板来处理它(这是标准库函数)。
#include <functional>
#include <iostream>
double finder(double a, double b = 0) {
return a + b;
};
template<typename Func, typename... Args>
double var_finder(double c, Func&& f, Args&&... args) {
return c * std::forward<Func>(f)(std::forward<Args>(args)...);
};
template<typename Func, typename... Args>
double var_finder(double c, Func&& f) {
return c * std::forward<Func>(f)();
};
class c_test
{
public:
double finder(double a, double b = 0) {
return a + b;
};
};
int main () {
double a = 2.0;
double b = 0.0;
// use as usual
std::cout << var_finder(0.1, finder, a, b) << std::endl;
// use with lambda
std::cout << var_finder(0.1, [a,b](){ return a+b; }) << std::endl;
// lambda with member argument, less gruesome than a variadic template calling a member function
c_test c;
std::cout << var_finder(0.1, [a,b, &c](){ return c.finder(a,b); }) << std::endl;
return 0;
}
关于C++11 可变参数模板在类中调用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62211078/