C++ 如何使用 std::function 编写指向成员函数的指针?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9281172/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do i write a pointer-to-member-function with std::function?
提问by
I know how to declare int fn(double)
inside of std::function (std::function<int(double)>
). I know how to write a pointer-to-member-function (typedef int (A::*MemFn)(double d);
). But how do i write a pointer-to-member-function with std::function?
我知道如何int fn(double)
在 std::function ( std::function<int(double)>
)内部声明。我知道如何编写指向成员函数的指针 ( typedef int (A::*MemFn)(double d);
)。但是如何使用 std::function 编写指向成员函数的指针?
Dummy code if you feel like compiling/testing
如果您想编译/测试,则使用虚拟代码
-edit- based on answers i think i'll just use the typedef and not bother with 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);
}
采纳答案by Nicol Bolas
std::function
is perfectly capable of storing a member function pointer directly. However, you have to adjust the argument list appropriately. Member pointers must be called with an instance of the type (or a derived type). When putting them in a std::function
, the first argument in the argument list is expected to be a pointer (or reference or smart-pointer) to the object type.
std::function
完全能够直接存储成员函数指针。但是,您必须适当调整参数列表。必须使用类型(或派生类型)的实例调用成员指针。将它们放入 a 时std::function
,参数列表中的第一个参数应该是指向对象类型的指针(或引用或智能指针)。
So, if I have the following class:
所以,如果我有以下课程:
struct Type
{
public:
int Foo();
};
The correct syntax to store this member function in a std::function
is:
将此成员函数存储在 a 中的正确语法std::function
是:
std::function<int(Type&)> fooCaller = &Type::Foo;
If you want to preserve the argument list (in your case, int(double)
), then you need to provide the instance outside of the function
. This can be done via std::bind
:
如果要保留参数列表(在您的情况下为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);
Note that it is your responsibilityto ensure that the object pointer you provide to std::bind
remains alive so long as fnCaller
is alive. If you return fnCaller
to someone, and it has a pointer to a stack object, you're in trouble.
请注意,您有责任确保您提供给的对象指针只要std::bind
还活着就一直fnCaller
活着。如果你返回fnCaller
给某人,并且它有一个指向堆栈对象的指针,那么你就有麻烦了。
What's nice is that you could bind a shared_ptr
(or any copyable smart pointer) as your object, thanks to how the function call mechanism is defined:
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);
Now you don't have to worry; the binder will continue to keep the object alive, since it stores a shared_ptr
by value.
现在您不必担心;活页夹将继续使对象保持活动状态,因为它存储了一个shared_ptr
by 值。
回答by Kerrek SB
A member function is not a function. It is not itself anything you can call. All you can do is call a member function of an instance object. Only the pair of pointer-to-member-function andobject constitutes a callable entity.
成员函数不是函数。它本身不是您可以调用的任何东西。您所能做的就是调用实例对象的成员函数。只有指向成员函数的指针和对象的对构成可调用实体。
To bind an instance to a PTMF and obtain something callable, use bind
:
要将实例绑定到 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'); //...
As with lambdas, bind expressions have an unknowable type, and the conversion to std::function
(as well as the actual dispatch) is potentially expensive. If possible, it is preferable to use auto
for the type of the bind expression.
与 lambda 一样,绑定表达式具有不可知的类型,并且转换为std::function
(以及实际调度)可能很昂贵。如果可能,最好使用auto
用于绑定表达式的类型。
回答by davidhigh
One of the guidelines in Scott Meyer's Modern C++11 book is to avoid std::bind
and always use a lambda closure instead:
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); };
The mutable
is necessary here, as the capture a
might potentially be changed by the function call (since A::fn
is non-const).
这里mutable
是必需的,因为a
函数调用可能会更改捕获(因为A::fn
是非常量)。
回答by Mark Ingram
If you can use Boost
then you can use Boost.Bind. It's easily accomplished like this:
如果可以使用,Boost
则可以使用Boost.Bind。它很容易完成,如下所示:
boost::bind(&MyClass::MemberFunction, pInstance, _1, _2)
Hopefully it's fairly self-explanatory. _1
and _2
are placeholders for parameters you can pass through to the function.
希望它是不言自明的。_1
和_2
是可以传递给函数的参数的占位符。
回答by Bojan Komazec
You can use std::binder1st
to bind member function to a class instance:
您可以使用std::binder1st
将成员函数绑定到类实例:
typedef std::binder1st<std::mem_fun1_t<int, A, double>> MemFn;
void Test(A* a, double d)
{
MemFn fn(std::mem_fun(&A::fn), a);
int nRetVal = fn(d);
}
int main()
{
Test(new A, 1.2f);
return 0;
}