29 c++
我知道如何int fn(double)在std :: function(std::function<int(double)>)中声明.我知道如何编写指向成员函数的指针(typedef int (A::*MemFn)(double d);).但是我如何使用std :: function编写指向成员函数的指针?
如果您想编译/测试,请使用虚拟代码
-edit-基于答案我认为我只会使用typedef而不是打扰std :: function
#include <cstdio>
#include <functional>
struct A{ int fn(double){ return 0; } };
int fn2(double){ return 0; }
typedef int (A::*MemFn)(double d);
typedef std::function<int(double)> MemFn2;
void Test(A*a, MemFn2 fn){
fn(1.2f);
}
void Test(A*a, MemFn fn){
(a->*fn)(1.2f);
}
int main(){
Test(new A, &A::fn);
Test(new A, &fn2);
}
Run Code Online (Sandbox Code Playgroud)
Nic*_*las 26
std::function完全能够直接存储成员函数指针.但是,您必须适当调整参数列表.必须使用类型(或派生类型)的实例调用成员指针.将它们放入a时std::function,参数列表中的第一个参数应该是对象类型的指针(或引用或智能指针).
所以,如果我有以下课程:
struct Type
{
public:
int Foo();
};
Run Code Online (Sandbox Code Playgroud)
在a中存储此成员函数的正确语法std::function是:
std::function<int(Type&)> fooCaller = &Type::Foo;
Run Code Online (Sandbox Code Playgroud)
如果你想保留参数列表(在你的情况下int(double)),那么你需要在function.之外提供实例.这可以通过std::bind以下方式完成:
struct A{ int fn(double){ return 0; } };
A anInstance;
std::function<int(double)> fnCaller = std::bind(&A::fn, &anInstance, std::placeholders::_1);
Run Code Online (Sandbox Code Playgroud)
请注意,您有责任确保您提供的对象指针std::bind保持活动状态,只要它还fnCaller活着.如果你回到fnCaller某人,并且它有一个指向堆栈对象的指针,那你就麻烦了.
有什么好处是你可以绑定一个shared_ptr(或任何可复制的智能指针)作为你的对象,这要归功于如何定义函数调用机制:
struct A{ int fn(double){ return 0; } };
auto anInstance = std::make_shared<A>();
std::function<int(double)> fnCaller = std::bind(&A::fn, anInstance, std::placeholders::_1);
Run Code Online (Sandbox Code Playgroud)
现在你不必担心; 绑定器将继续保持对象存活,因为它存储了一个shared_ptrby值.
Ker*_* SB 10
成员函数不是函数.它本身并不是你可以称之为的东西.您所能做的就是调用实例对象的成员函数.只有指向成员函数和对象的对构成可调用实体.
要将实例绑定到PTMF并获取可调用的内容,请使用bind:
#include <functional>
struct Foo
{
double bar(bool, char);
};
Foo x;
using namespace std::placeholders;
std::function<double(bool, char)> f = std::bind(&Foo::bar, x, _1, _2);
f(true, 'a'); //...
Run Code Online (Sandbox Code Playgroud)
与lambda一样,绑定表达式具有不可知的类型,转换为std::function(以及实际的调度)可能很昂贵.如果可能,最好使用auto绑定表达式的类型.
Scott Meyer的Modern C++ 11书中的一个指导原则是避免std::bind并始终使用lambda闭包:
struct A{ int fn(double){ return 0; } };
std::function<int(double)> f = [a = A{}](double x) mutable { return a.fn(x); };
Run Code Online (Sandbox Code Playgroud)
这mutable是必要的,因为a函数调用可能会改变捕获(因为A::fn它是非const).