我遇到了“动态”创建指向成员函数(PTMF)类型的变量的问题(即通过std :: bind固定现有成员函数的一些参数)。我的问题是,如果有可能使用C ++ 11或后C ++ 11标准。
Preambula:我有一个类,它存储从PTMF初始化的std :: functions的静态const数组,以下称为“处理程序”。最初,它们是具有名称和实现的常规成员函数,所以我从未使用过C ++ 11和std :: function。然后,我决定他们中的许多人几乎相似,并决定使用“生成器功能”生成它们。我想避免使用模板进行生成,因为这些几乎相似的处理程序的数量将来会大幅增加(大约200+),而模板化只会导致代码膨胀。
如果有问题的PTMF是静态的,我通过std :: bind生成处理程序没有问题。一个简化的例子:
#include <iostream>
#include <functional>
using namespace std;
struct A {
typedef function<void(int)> HandlerFn;
static void parametrized_handler(int i, const char *param) {
cout << "parametrized handler: " << param << endl;
}
static void handler(int i) { cout << "handler 1" << endl; }
int mm;
};
static const A::HandlerFn handler2 = [](int) { cout << "handler 2" << endl; };
static const A::HandlerFn handler3 = bind(A::parametrized_handler,
placeholders::_1,
"test_param");
int main()
{
A::handler(42);
handler2(42);
handler3(42);
return 0;
}
输出:
$ ./a.out
handler 1
handler 2
parametrized handler: test_param
当我转向非静态成员函数时出现问题。 std :: bind无法生成一个像PTMF一样的函数对象。我知道我可以传递一个真实的对象作为第一个参数来绑定并获得一个工作函数,但这不是我想要的:当我初始化一个静态const数组时,根本就没有对象,而bind的结果将是无论如何,充当常规的非会员职能。
非静态成员函数的预期实现(使用虚构的std :: bind_mem绑定器):
#include <iostream>
#include <functional>
using namespace std;
struct A;
struct A {
typedef function<void(int)> HandlerFn;
void parametrized_handler(int i, const char *param) {
mm;
cout << "parametrized handler: " << param << endl;
}
void handler(int i) const { mm; cout << "handler 1" << endl; }
const HandlerFn handler2 = [this](int i) { mm; cout << "handler 2" << endl; };
int mm;
};
// An imaginary PTMF binder
// static const A::HandlerFn handler3 = bind_mem(A::parametrized_handler,
// placeholders::_1,
// "test_param");
int main()
{
A a;
(a.handler)(42);
(a.handler2)(42);
//(a.handler3)(42);
return 0;
}
输出:
$ ./a.out
handler 1
handler 2
那么有没有办法实现PTMF参数绑定?
要将指针绑定到非静态成员函数,您需要一个对象。
#include<functional>
struct A {
typedef std::function<void(int)> HandlerFn;
void mem(int);
void static static_mem(int);
};
void foo() {
A a;
A::HandlerFn h1 = A::static_mem;
//This captures a by ref
A::HandlerFn h2 = std::bind(&A::mem, std::ref(a), std::placeholders::_1);
//This captures a by copy
A::HandlerFn h3 = std::bind(&A::mem, a, std::placeholders::_1);
//Change to =a for copy
A::HandlerFn h4 = [&a](int i){
a.mem(i);
};
h1(34);
h2(42);
}