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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 12:36:19  来源:igfitidea点击:

How do i write a pointer-to-member-function with std::function?

c++

提问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::functionis 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::functionis:

将此成员函数存储在 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::bindremains alive so long as fnCalleris alive. If you return fnCallerto 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_ptrby value.

现在您不必担心;活页夹将继续使对象保持活动状态,因为它存储了一个shared_ptrby 值。

回答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 autofor 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::bindand 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 mutableis necessary here, as the capture amight potentially be changed by the function call (since A::fnis non-const).

这里mutable是必需的,因为a函数调用可能会更改捕获(因为A::fn是非常量)。

回答by Mark Ingram

If you can use Boostthen 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. _1and _2are placeholders for parameters you can pass through to the function.

希望它是不言自明的。_1_2是可以传递给函数的参数的占位符。

回答by Bojan Komazec

You can use std::binder1stto 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;
}