繁体   English   中英

如何用std :: function编写指向成员函数的指针?

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

我知道如何在std :: function( std::function<int(double)> )中声明int fn(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);
}

std::function完全能够直接存储成员函数指针。 但是,您必须适当调整参数列表。 必须使用类型(或派生类型)的实例调用成员指针。 将它们放在std::function ,参数列表中的第一个参数应该是对象类型的指针(或引用或智能指针)。

所以,如果我有以下课程:

struct Type
{
public:
    int Foo();
};

std::function存储此成员函数的正确语法是:

std::function<int(Type&)> fooCaller = &Type::Foo;

如果要保留参数列表(在您的情况下为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);

请注意,只要fnCaller活动状态, 就有责任确保提供给std::bind的对象指针保持活动状态。 如果你将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);

现在你不必担心; 绑定器将继续保持对象的活动,因为它按值存储shared_ptr

成员函数不是函数。 它本身并不是你可以称之为的东西。 您所能做的就是调用实例对象的成员函数。 只有指向成员函数对象的对构成可调用实体。

要将实例绑定到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'); //...

与lambdas一样,绑定表达式具有不可知的类型,并且转换为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); };

这里需要mutable ,因为函数调用可能会改变捕获a (因为A::fn是非const)。

您可以使用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;
}

如果你可以使用Boost那么你可以使用Boost.Bind 这很容易实现:

boost::bind(&MyClass::MemberFunction, pInstance, _1, _2)

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM