我正在研究如何用c ++ 11实现简单的委托。 disconnect-method的问题,我想针对要从地图中删除的特定对象的特定功能。通过此实现,我擦除连接到特定对象实例的所有函数。我希望能够做到这样的事情:
delegate.disconnect (myobj, &MyObj::method)
而不是
delegate.disconnect (myobj)
删除myobj的所有connceted函数。
template <typename ... Params >
class Delegate {
private:
typedef std::function < void (Params...)> FunctionType;
std::map < void*, std::vector < FunctionType >> m_functions;
public:
template <typename Class>
void connect(Class& obj, void (Class::*func) (Params...) )
{
std::function < void (Class, Params...) > f = func;
FunctionType fun = [&obj, f](Params... params) { f(obj, params...); };
m_functions[&obj].push_back(fun);
}
template <typename Class>
void disconnect(Class& obj) {
m_functions.erase(&obj);
}
template <typename ... Args>
void operator() (Args...args)
{
for (auto& pair : m_functions) {
for (auto& func : pair.second) {
func(args...);
}
}
}
};
答案 0 :(得分:1)
std :: function仅与nullptr_t see here
相当出于这个原因,我将使用类似于下面提供的解决方案,其中返回的对象在破坏期间使用迭代器取消映射。当然,其中一个需要一个容器,它的迭代器不会失效。可以编写各种类似的习语,并且可以尝试使其完全通用。我刚刚提供了这个想法,但(在下面这里):
由于映射迭代器在插入时没有失效,我通常会返回一个包装迭代器的对象,并在超出范围时使用迭代器取消映射:
它看起来像这样......
struct Resource{ virtual ~Resource(){} };
template <class SubjectT, class IterT>
struct Unmapper : Resource
{
typedef void (SubjectT::*UnmapFunc)( IterT );
Unmapper(
std::shared_ptr<SubjectT> subject, UnmapFunc unmap, IterT ref )
: subject_( subject ), ref_( ref ), unmap_( unmap )
{
}
~Unmapper()
{
std::shared_ptr<SubjectT> subject = subject_.lock();
if( subject ){ ((*subject).*unmap_)( ref_ ); }
}
private:
std::weak_ptr<SubjectT> subject_;
IterT ref_;
UnmapFunc unmap_;
};
template <class SubjectT, class IterT>
std::unique_ptr<Resource> makeUnmapper( std::shared_ptr<SubjectT> subject,
void (SubjectT::*unmapFunc)( IterT ), IterT ref )
{
return std::unique_ptr<Resource>(
new Unmapper<SubjectT, IterT>( subject, unmapFunc, ref ) );
}
......和......
//Could generalise by using variadic templates, yes...
class Subject : public std::enable_shared_from_this
{
public:
typedef std::function<void()> my_function;
std::unique_ptr<Resource> subscribe( int id, my_function func )
{
//psuedo code...
my_map::iterator pos = myMap_.insert( id, func );
if( pos.second )
{
return makeUnmapper( shared_from_this(), &Subject::unmap, pos );
}
else throw already_subscribed();
}
private:
//etc... declare map etc...
void unmap( my_map::iterator pos ){ myMap_.erase( pos ); }
};
注意: 我没有编译这个。我可能错过了一个动作,但我对此表示怀疑,因为unique_ptr总是rvalues。
答案 1 :(得分:0)
我找到了一种方法来散列成员函数,这是我需要的,所以我在这里回答我自己的问题:
template <typename Class>
size_t getHash(void (Class::*func) (Params...)) {
const char *ptrptr = static_cast<const char*>(static_cast<const void*>(&func));
int size = sizeof (func);
std::string str_rep(ptrptr, size);
std::hash<std::string> strHasher;
return strHasher(str_rep);
}
用法现在很简单:
delegate.disconnect(&MyClass::MyFunc);