c++如何将成员函数一般地转换为独立函数(用作函数参数)
C++ how to convert member functions to standalone functions (for use as function parameter) generically?
对于模板函数的函数参数,我发现自己经常将成员函数包装在lambda中以创建相同的独立函数,第一个参数为对象。
(虚拟)示例:
class A
{
public:
double f1() const;
double f2(int i) const;
// some data
};
template <typename Func>
double calculateSum(std::vector<A> as, Func f)
{
double result = 0.0;
for (auto a : as)
result += f(a);
return result;
}
int main()
{
std::vector<A> as;
int i = 0;
auto sum1 = calculateSum(as, [](const A& a) { return a.f1(); });
auto sum2 = calculateSum(as, [&i](const A& a) { return a.f2(i); });
return 0;
}
是否有一种方法来定义这样的lambdas更一般?或者有一种方法可以直接引用成员函数,而不是使用lambda ?
您可以使用c++ 14泛型lambdas来帮助完成此操作。像这样定义你的泛型lambda:
auto bindMem = [](auto f, auto& ... memArgs) { return [f, &memArgs...](auto& a) { return (a.*f)(memArgs...); }; };
要理解:这会创建一个泛型lambda,调用它会产生另一个lambda。第一个lambda获取您想要调用的成员函数,以及任何绑定参数(this
对象除外)。它生成第二个lambda,然后该lambda期望对象本身,并使用前面绑定的形参对其应用成员函数调用。
对于你的用例,你有一个整洁的:
auto sum1 = calculateSum(as, bindMem(&A::f1));
auto sum2 = calculateSum(as, bindMem(&A::f2,i));
这样做的好处是,完全相同的bindMem
lambda将适用于任何类和任何成员函数,具有任意参数列表。所以它确实是通用的
经过一番研究,感谢@happydave的建议,我将采用以下答案:
auto sum1 = calculateSum(as, std::mem_fn(&A::f1));
第二个和不能这样处理,应该保持为lambda。然而,一般来说,客户机代码是参数提供者的情况似乎不太可能出现(在这种情况下,需要将参数无论如何传递给模板函数(lambda捕获是一种很好的方法))。在许多情况下,模板函数还提供传递的函数的参数,std::mem_fn就可以了。
您可以使用std::bind()
。
Bind接受一个函数和您想要使用的许多参数,并返回一个不错的std::function
对象。您可以在创建时指定参数,也可以在调用返回函数时使用占位符指定参数。
#include <functional>
...
auto sum1 = calculateSum(as, std::bind(&A::f1, std::placeholders::_1));
auto sum2 = calculateSum(as, std::bind(&A::f2, std::placeholders::_1, i);
请记住,非静态成员函数将类实例作为其第一个参数(尽管大多数情况下是隐式的,这不是其中之一),这就是我们使用占位符的原因。当您现在执行f(a)
时,a
(类实例)将替换占位符。
进一步阅读:Bind, placeholder
- 查找存储在二叉搜索树的所有非叶子中的数据总和?(返回整数的独立递归函数
- 为什么C++哈希函数的返回类型是 std::size_t,而不是独立于平台的类型?
- 为什么"C++ Core Guidelines"推荐首选独立函数而不是类成员?
- Doxygen不会为独立函数生成文档
- 从独立函数中调用成员函数
- 定义可以执行对象方法和独立函数的函数时出现问题
- 在每个实例中,使成员函数中的静态变量独立
- 独立于元素内存管理的向量上的函数
- 调用 std::线程,指针指向独立函数
- 创建独立于构造函数的对象指针
- DBUS 代码在放置在守护进程内时崩溃,但在没有守护进程代码的独立独立 main() 函数中运行良好
- 为什么std::whatever::erase()是一个方法,std::remove()是独立函数
- 获得快速的k对独立散列函数的选项是什么
- 如何使用独立于索引的函数初始化向量
- 如何在C++上独立运行函数
- 调用需要具有结构的独立参数的 C++ 函数是否安全
- 类模板的所有实例化是否可以共享相同的模板独立成员函数
- 我应该把这些函数放在一个独立的.h文件中吗
- Visual Studio 2010-独立函数中存在链接器错误
- 如何将两个独立的boost::bind()组合为一个boost::函数