使用std :: function和std :: bind来存储回调和处理对象删除。 [英] Using std::function and std::bind to store callback and handle object deletion.
问题描述
我想实现一个管理器,使用C ++ 11存储多态类的成员函数的回调。问题是,我不知道如何处理的情况下,该成员属于的对象被删除或应删除,我想让界面尽可能简单。
所以我想到了以下内容:将 std :: weak_ptr
存储到对象以及 std :: function
给成员。
以下似乎有效:
class MyBase {
public:
MyBase(){}
virtual〜MyBase(){}
};
// -------------------------------------------- ------
class MyClass:public MyBase {
public:
MyClass():MyBase(){}
void myDouble {std :: cout< 价值是:< val<< std :: endl; }
};
// -------------------------------------------- ------
类管理器{
public:
void setFunction(std :: weak_ptr< MyBase> base,std :: function< void(double)> func){
m_function.first = base;
m_function.second = func;
}
private:
std :: pair< std :: weak_ptr< MyBase>,std :: function< void(double)> m_function;
};
使用:
Manager db;
std :: shared_ptr< MyClass> myClass = std :: make_shared< MyClass>();
db.setFunction(myClass,std :: bind(& MyClass :: myDouble,myClass,std :: placeholders :: _ 1));
现在我想隐藏 std :: bind
部分,所以他只需要调用:
db.setFunction(myClass,& MyClass :: myDouble);
所以我想在我的经理功能中得到几乎以下的工作:
void setFunc2(std :: weak_ptr< MyBase> base,std :: function< void(double)> func){
m_function.first = base;
m_function.second = std :: bind(func,base,std :: placeholders :: _ 1);
}
但上述错误:
错误:不匹配'operator ='(操作数类型为'std :: function< void(double)>'和
'std :: _ Bind_helper< ; false,std :: function< void(double)>& std :: weak_ptr< MyBase>& const std :: _ placeholder< 1>&> :: type {aka std :: _ Bind< std :: function< void(double)>(std :: weak_ptr< MyBase> std :: _ Placeholder< 1>)>}')
m_function.second = std :: bind(func,base,std :: placeholder :: _ 1);
有更好的方法来做到这一点, >
我注意到有趣的东西。如果我使用 std :: shared_ptr
, use_count()
std :: bind 。因此,我不能手动重置/销毁对象,除非我取消了我的经理的成员。此行为记录在哪里,我通常使用 cppreference ?
我看了下面的问题,但似乎不能得到它的工作对我的问题:如何使用多态与std :: function?
code> setFunction ,以便您可以接受指向成员的派生,并且不必为cv / ref限定符的组合写入12个重载。
模板<类D,类D2,类F>
void setFunction(const std :: shared_ptr< D& sp,F D2 :: * member){
//可选static_assert,D2是D的基础。
m_function.first = sp;
m_function.second = std :: bind(member,sp.get(),std :: placeholders :: _ 1);
}
显然你需要确保你 lock在调用
m_function.second
之前 m_function.first
。
或者,只需使用捕获 weak_ptr
和成员函数指针的lambda:
std :: function< void(double)> m_function;
template< class D,class D2,class F>
void setFunction(const std :: shared_ptr< D& sp,F D2 :: * member){
std :: weak_ptr< D& wp = sp;
m_function = [wp,member](double d){
if(auto sp = wp.lock()){
((* sp)。
}
else {
//句柄指针不再有效的情况。
}
};
}
I want to implement a manager that stores callbacks to member functions of polymorphic classes using C++11. The issue is that I am not sure how to handle the case where the object that the member belongs to gets deleted or should be deleted and I want to make the interface as simple as possible.
So I thought of the following: Store a std::weak_ptr
to the object as well as a std::function
to the member.
The following seems to work:
class MyBase {
public:
MyBase() {}
virtual ~MyBase() {}
};
//--------------------------------------------------
class MyClass : public MyBase {
public:
MyClass() : MyBase() {}
void myDouble(double val) const { std::cout << "Value is: " << val << std::endl; }
};
//--------------------------------------------------
Class Manager {
public:
void setFunction(std::weak_ptr<MyBase> base, std::function<void(double)> func) {
m_function.first = base;
m_function.second = func;
}
private:
std::pair<std::weak_ptr<MyBase>, std::function<void(double)>> m_function;
};
To use this:
Manager db;
std::shared_ptr<MyClass> myClass = std::make_shared<MyClass>();
db.setFunction(myClass, std::bind(&MyClass::myDouble, myClass, std::placeholders::_1));
Now I want to hide the std::bind
part from the user, so that he only needs to call:
db.setFunction(myClass, &MyClass::myDouble);
So I want to get almost the following working in my manager function:
void setFunc2(std::weak_ptr<MyBase> base, std::function<void(double)> func) {
m_function.first = base;
m_function.second = std::bind(func, base, std::placeholders::_1);
}
But the above gives errors:
error: no match for 'operator=' (operand types are 'std::function<void(double)>' and
'std::_Bind_helper<false, std::function<void(double)>&, std::weak_ptr<MyBase>&, const std::_Placeholder<1>&>::type {aka std::_Bind<std::function<void(double)>(std::weak_ptr<MyBase>, std::_Placeholder<1>)>}')
m_function.second = std::bind(func, base, std::placeholders::_1);
Is there a better way to do this, or perhaps a way to get this working?
Something interesting that I notice. If I use the std::shared_ptr
the use_count()
gets incremented with the call to std::bind
in the original code. Thus I can not manually reset/destroy the object unless I unset the member on my manager. Where is this behaviour documented, I normally use cppreference?
I have looked at the following question but can't seem to get it working for my problem: How can I use polymorphism with std::function?
Template setFunction
so that you can accept pointer-to-member-of-derived, and don't have to write 12 overloads for the combinations of cv/ref qualifiers.
template<class D, class D2, class F>
void setFunction(const std::shared_ptr<D> &sp, F D2::* member) {
// optionally static_assert that D2 is a base of D.
m_function.first = sp;
m_function.second = std::bind(member, sp.get(), std::placeholders::_1);
}
Obviously you need to make sure you lock()
m_function.first
before calling m_function.second
.
Alternatively, just use a lambda that captures both the weak_ptr
and the member function pointer:
std::function<void(double)> m_function;
template<class D, class D2, class F>
void setFunction(const std::shared_ptr<D> &sp, F D2::* member) {
std::weak_ptr<D> wp = sp;
m_function = [wp, member](double d) {
if(auto sp = wp.lock()){
((*sp).*member)(d);
}
else {
// handle pointer no longer valid case.
}
};
}
这篇关于使用std :: function和std :: bind来存储回调和处理对象删除。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!