想要存储以下内容:
typedef std::function<void(int)> MyFunctionDecl;
..在一个集合中:
typedef std::vector<MyFunctionDecl> FunctionVector;
FunctionVector v;
这是可能的,但如果我想使用std::find
找到某些内容:
FunctionVector::const_iterator cit = std::find(v.begin(), v.end(), myFunctionDecl);
..由于==
运算符,我们收到错误。
正如我之前提出的有关此问题的建议,可以通过将函数声明封装在另一个类中来实现,该类提供==
运算符:
class Wrapper
{
private:
MyFunctionDecl m_Func;
public:
// ctor omitted for brevity
bool operator == (const Wrapper& _rhs)
{
// are they equal?
}; // eo ==
}; // eo class Wrapper
所以我想要做的是以某种方式为“MyFunctionDecl”生成一个哈希,以便我可以正确实现==
运算符。我可以拥有某种唯一标识符,并要求调用者为委托提供唯一标识符,但这看起来有点痛苦并且容易出错。
有没有办法可以做到这一点?为了比较的目的,相同的函数将返回相同的ID?到目前为止,唯一的解决方法是抛弃使用std::function
的概念,然后回到使用支持比较的快速代理。但后来我失去了使用lambdas的能力。
任何帮助表示赞赏!
修改
鉴于下面的答案,这就是我想出的......我可能错过的任何警告?我现在正在通过它的步伐:
class MORSE_API Event : boost::noncopyable
{
public:
typedef std::function<void(const EventArgs&)> DelegateType;
typedef boost::shared_ptr<DelegateType> DelegateDecl;
private:
typedef std::set<DelegateDecl> DelegateSet;
typedef DelegateSet::const_iterator DelegateSet_cit;
DelegateSet m_Delegates;
public:
Event()
{
}; // eo ctor
Event(Event&& _rhs) : m_Delegates(std::move(_rhs.m_Delegates))
{
}; // eo mtor
~Event()
{
}; // eo dtor
// methods
void invoke(const EventArgs& _args)
{
std::for_each(m_Delegates.begin(),
m_Delegates.end(),
[&_args](const DelegateDecl& _decl) { (*_decl)(_args); });
}; // eo invoke
DelegateDecl addListener(DelegateType f)
{
DelegateDecl ret(new DelegateType(f));
m_Delegates.insert(ret);
return ret;
}; // eo addListener
void removeListener(const DelegateDecl _decl)
{
DelegateSet_cit cit(m_Delegates.find(_decl));
if(cit != m_Delegates.end())
m_Delegates.erase(cit);
}; // eo removeListener
}; // eo class Event
答案 0 :(得分:6)
你看过Boost Signals了吗?它可能已经在做你想做的事了。
无论如何,包裹function
的简单方法是使用shared_ptr
。如果你这样做
typedef std::shared_ptr<std::function<void(int)> > MyFunctionDecl;
并确保函数在创建时立即包装在shared_ptr
内(以便指针是唯一的),可以测试指针的相等性,以便std::find
可以工作。
例如,您可以使用像
这样的工厂函数来执行此操作template <class Functor>
MyFunctionDecl createDelegate(Functor f) {
return MyFunctionDecl(new std::function<void(int)>(f));
}
这样,在创建委托时,您可以为函数(其指针)赋予唯一标识。
顺便说一句,我使用的是std::set
而不是std::vector
,因为find
和erase
都是对数而不是线性。
答案 1 :(得分:-1)
#include <boost/type_traits.hpp>
#include <iostream>
template<typename T>
class Wrapper
{
private:
T m_Func;
public:
template<typename U>
bool operator==(const Wrapper<U>& _rhs)
{
return boost::is_same<T, U>::value;
}
};
int main()
{
Wrapper<int> Wint;
Wrapper<bool> Wbool;
std::cout << (Wint == Wbool) << std::endl;
std::cout << (Wint == Wint) << std::endl;
}