c – 使用std :: function进行回调的Alterantive
作者:互联网
目前我正在尝试一个基本上具有以下功能的代码:
void f(int x) { cout << "f("<<x<<")" << endl; }
class C
{
public:
void m(int x) { cout << "C::m("<<x<<")" << endl; }
};
class C2
{
public:
void registerCallback(function<void(int)> f)
{
v.push_back(f);
}
private:
vector<function<void(int)>> v;
void callThem()
{
for (int i=0; i<v.size(); i++)
{
v[i](i);
}
}
};
int main()
{
C2 registrar;
C c;
registrar.registerCallback(&f); // Static function
registrar.registerCallback(bind(&C::m, &c, placeholders::_1)); // Method
return 0;
}
这非常有效.但是我遇到了这种模式.我想检查一个回调是否已经注册,我希望能够通过从向量中删除它来取消注册回调.我刚刚了解到无法比较std :: function对象,这意味着无法在容器中搜索它们的存在.
所以我需要另一种选择.当然我想保持编译时类型检查和注册任意类方法的能力.
如何实现允许取消注册回调和检查双重注册的类似解决方案?我需要接受任何权衡吗?
解决方法:
根本问题是大多数功能对象无法比较.虽然可以比较普通函数指针和具有相等运算符的用户定义函数对象,但是lambdas,std :: bind()等的结果却不能.使用函数对象的地址来识别它们通常不是合适的方法,因为对象往往被复制.可以使用std :: reference_wrapper< Fun>避免复制它们但存储在std :: function< F>中的对象仍然会有不同的地址.
使用C 11可变参数模板,可以非常轻松地创建自定义版本的std :: function< ...>提供比较设施.甚至可能有两个版本:
>一个版本接受任意函数对象,但显然只能比较可比较的函数对象:取决于构造函数参数是否提供了相等运算符,使用了合适的基类.
>一个版本总是提供工作比较,显然,不能与不等同的对象一起使用.
后者稍微容易定义,看起来像这样:
template <typename...> class comparable_function;
template <typename RC, typename... Args>
class comparable_function<RC(Args...)> {
struct base {
virtual ~base() {}
virtual RC call(Args... args) = 0;
virtual base* clone() const = 0;
virtual bool compare(base const*) const = 0;
};
template <typename Fun>
struct concrete: base {
Fun fun;
concrete(Fun const& fun): fun(fun) {}
RC call(Args... args) { return this->fun(args...); }
base* clone() const { return new concrete<Fun>(this->fun); }
bool compare(base const* other) const {
concrete const* o = dynamic_cast<concrete<Fun>>(other);
return o && this->fun == o->fun;
}
};
std::unique_ptr<base> fun;
public:
template <typename Fun>
comparable_function(Fun fun): fun(new concrete<Fun>(fun)) {}
comparable_function(comparable_function const& other): fun(other.fun->clone()) {}
RC operator()(Args... args) { return this->fun->call(args); }
bool operator== (comparable_function const& other) const {
return this->fun->compare(other.fun.get());
}
bool operator!= (comparable_function const& other) { return !(this == other); }
};
我想,我已经忘记(和/或错误)某些东西,而不是那就是需要的东西.对于可选的可比较版本,您有两个版本的混凝土:一个是上面实现的,另一个总是返回false.根据构造函数中的Fun是否有运算符==,您可以创建一个或另一个.
标签:std-function,stdbind,c,c11,callback 来源: https://codeday.me/bug/20190830/1766693.html