c++11: std::bind 用于子类成员函数
c++11: std::bind for sub-class member-functions
我想调用 classes 的运行时绑定函数,它们继承了通用 class "Bindable" 的绑定能力。这真的可能吗?
这是一个存根,肯定缺少很多模板参数和名称空间:
#include <iostream> // std::cout
#include <functional> // std::bind
#include <map> // std::map
class Bindable {
public:
void bindFunction (int x, auto newFn) {
mFns.insert(std::pair<int, auto>(x,newFn));
}
void invokeFunction (int key) {
mFns.at(key)();
}
protected:
std::map<int, function> mFns;
};
class A : Bindable {
void funAone (void) {
cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
cout << "called funAtwo" <<std::endl;
}
};
class B : Bindable {
void funBone (void) {
cout << "called funBone" <<std::endl;
}
void funBtwo (void) {
cout << "called funBtwo" <<std::endl;
}
};
int main() {
A a;
B b;
a.bindFunction(1, &A::funAone);
a.bindFunction(2, &A::funAtwo);
b.bindFunction(1, &B::funBone);
b.bindFunction(2, &B::funBtwo);
a.invokeFunction(1);
a.invokeFunction(2);
b.invokeFunction(1);
b.invokeFunction(2);
}
是的,可以,使用 std::bind。请注意,auto
不能用作函数或模板参数。
#include <iostream> // std::cout
#include <functional> // std::bind
#include <map> // std::map
class Bindable {
public:
typedef std::function<void()> Function;
void bindFunction (int x, Function newFn) {
mFns.insert(std::pair<int, Function>(x,newFn));
}
void invokeFunction (int key) {
mFns.at(key)();
}
protected:
std::map<int, Function > mFns;
};
class A : public Bindable {
public:
void funAone (void) {
std::cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
std::cout << "called funAtwo" <<std::endl;
}
};
class B : public Bindable {
public:
void funBone (void) {
std::cout << "called funBone" <<std::endl;
}
void funBtwo (void) {
std::cout << "called funBtwo" <<std::endl;
}
};
int main() {
A a;
B b;
a.bindFunction(1, std::bind(&A::funAone, a)); // more than one way to bind
a.bindFunction(2, std::bind(&A::funAtwo, &a)); // the object parameter
b.bindFunction(1, std::bind(&B::funBone, b));
b.bindFunction(2, std::bind(&B::funBtwo, &b));
a.invokeFunction(1);
a.invokeFunction(2);
b.invokeFunction(1);
b.invokeFunction(2);
}
选项#1
使用 CRTP 惯用法 了解可以存储什么类型的成员函数指针:
template <typename T>
struct Bindable {
void bindFunction (int x, void(T::*newFn)()) {
mFns.insert(std::make_pair(x,newFn));
}
void invokeFunction (int key) {
(static_cast<T*>(this)->*mFns.at(key))();
}
protected:
std::map<int, void(T::*)()> mFns;
};
struct A : Bindable<A> {
void funAone (void) {
std::cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
std::cout << "called funAtwo" <<std::endl;
}
};
选项#2
使用类型擦除并使 bindFunction
成为函数模板:
struct Bindable {
template <typename T, typename std::enable_if<std::is_base_of<Bindable, T>{}, int>::type = 0>
void bindFunction (int x, void(T::*newFn)()) {
mFns.insert(std::make_pair(x, std::bind(newFn, static_cast<T*>(this))));
}
void invokeFunction (int key) {
mFns.at(key)();
}
protected:
std::map<int, std::function<void()>> mFns;
};
struct A : Bindable {
void funAone (void) {
std::cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
std::cout << "called funAtwo" <<std::endl;
}
};
在这两种情况下您都可以使用如下代码:
int main() {
A a;
B b;
a.bindFunction(1, &A::funAone);
a.bindFunction(2, &A::funAtwo);
b.bindFunction(1, &B::funBone);
b.bindFunction(2, &B::funBtwo);
a.invokeFunction(1);
a.invokeFunction(2);
b.invokeFunction(1);
b.invokeFunction(2);
}
输出:
called funAone
called funAtwo
called funBone
called funBtwo
我想调用 classes 的运行时绑定函数,它们继承了通用 class "Bindable" 的绑定能力。这真的可能吗?
这是一个存根,肯定缺少很多模板参数和名称空间:
#include <iostream> // std::cout
#include <functional> // std::bind
#include <map> // std::map
class Bindable {
public:
void bindFunction (int x, auto newFn) {
mFns.insert(std::pair<int, auto>(x,newFn));
}
void invokeFunction (int key) {
mFns.at(key)();
}
protected:
std::map<int, function> mFns;
};
class A : Bindable {
void funAone (void) {
cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
cout << "called funAtwo" <<std::endl;
}
};
class B : Bindable {
void funBone (void) {
cout << "called funBone" <<std::endl;
}
void funBtwo (void) {
cout << "called funBtwo" <<std::endl;
}
};
int main() {
A a;
B b;
a.bindFunction(1, &A::funAone);
a.bindFunction(2, &A::funAtwo);
b.bindFunction(1, &B::funBone);
b.bindFunction(2, &B::funBtwo);
a.invokeFunction(1);
a.invokeFunction(2);
b.invokeFunction(1);
b.invokeFunction(2);
}
是的,可以,使用 std::bind。请注意,auto
不能用作函数或模板参数。
#include <iostream> // std::cout
#include <functional> // std::bind
#include <map> // std::map
class Bindable {
public:
typedef std::function<void()> Function;
void bindFunction (int x, Function newFn) {
mFns.insert(std::pair<int, Function>(x,newFn));
}
void invokeFunction (int key) {
mFns.at(key)();
}
protected:
std::map<int, Function > mFns;
};
class A : public Bindable {
public:
void funAone (void) {
std::cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
std::cout << "called funAtwo" <<std::endl;
}
};
class B : public Bindable {
public:
void funBone (void) {
std::cout << "called funBone" <<std::endl;
}
void funBtwo (void) {
std::cout << "called funBtwo" <<std::endl;
}
};
int main() {
A a;
B b;
a.bindFunction(1, std::bind(&A::funAone, a)); // more than one way to bind
a.bindFunction(2, std::bind(&A::funAtwo, &a)); // the object parameter
b.bindFunction(1, std::bind(&B::funBone, b));
b.bindFunction(2, std::bind(&B::funBtwo, &b));
a.invokeFunction(1);
a.invokeFunction(2);
b.invokeFunction(1);
b.invokeFunction(2);
}
选项#1
使用 CRTP 惯用法 了解可以存储什么类型的成员函数指针:
template <typename T>
struct Bindable {
void bindFunction (int x, void(T::*newFn)()) {
mFns.insert(std::make_pair(x,newFn));
}
void invokeFunction (int key) {
(static_cast<T*>(this)->*mFns.at(key))();
}
protected:
std::map<int, void(T::*)()> mFns;
};
struct A : Bindable<A> {
void funAone (void) {
std::cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
std::cout << "called funAtwo" <<std::endl;
}
};
选项#2
使用类型擦除并使 bindFunction
成为函数模板:
struct Bindable {
template <typename T, typename std::enable_if<std::is_base_of<Bindable, T>{}, int>::type = 0>
void bindFunction (int x, void(T::*newFn)()) {
mFns.insert(std::make_pair(x, std::bind(newFn, static_cast<T*>(this))));
}
void invokeFunction (int key) {
mFns.at(key)();
}
protected:
std::map<int, std::function<void()>> mFns;
};
struct A : Bindable {
void funAone (void) {
std::cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
std::cout << "called funAtwo" <<std::endl;
}
};
在这两种情况下您都可以使用如下代码:
int main() {
A a;
B b;
a.bindFunction(1, &A::funAone);
a.bindFunction(2, &A::funAtwo);
b.bindFunction(1, &B::funBone);
b.bindFunction(2, &B::funBtwo);
a.invokeFunction(1);
a.invokeFunction(2);
b.invokeFunction(1);
b.invokeFunction(2);
}
输出:
called funAone
called funAtwo
called funBone
called funBtwo