【发布时间】:2013-04-10 03:02:05
【问题描述】:
这个问题完全是关于std::function 而不是boost::function。有关详细信息,请参阅此问题底部的 更新 部分,尤其是关于无法根据 C++11 标准比较非空 std::function 对象的部分。
C++11 std::function 类模板非常适合维护回调集合。例如,可以将它们存储在vector 中,并在需要时调用它们。然而,维护这些对象并允许注销似乎是不可能的。
让我具体一点,想象一下这个类:
class Invoker
{
public:
void Register(std::function<void()> f);
void Unregister(std::function<void()> f);
void InvokeAll();
private:
// Some container that holds the function objects passed to Register()
};
示例使用场景:
void foo()
{
}
int main()
{
std::function<void()> f1{foo};
std::function<void()> f2{[] {std::cout << "Hello\n";} };
Invoker inv;
// The easy part
// Register callbacks
inv.Register(f1);
inv.Register(f2);
// Invoke them
inv.InvokeAll();
// The seemingly impossible part. How can Unregister() be implemented to actually
// locate the correct object to unregister (i.e., remove from its container)?
inv.Unregister(f2);
inv.Unregister(f1);
}
Register() 函数是如何实现的相当清楚。但是,如何实现Unregister()。假设保存函数对象的容器是 vector<std::function<void()>> 。您如何找到传递给Unregister() 调用的特定函数对象? std::function 确实提供了重载的operator==,但它只测试空函数对象(即,它不能用于比较两个非空函数对象以查看它们是否都引用相同的实际调用)。
我会很感激任何想法。
更新:
目前的想法主要包括添加一个与每个std::function 对象关联的cookie,该对象可用于注销它。我希望有一些与std::function 对象本身无关的东西。此外,std::function 和 boost::function 之间似乎存在很多混淆。这个问题完全是关于std::function 对象,而不是 boost::function 对象。
此外,您不能比较两个非空 std::function 对象的相等性。根据标准,他们总是会比较不相等。因此,在此问题的上下文中,cmets 中指向执行此操作(并使用 boost::function 对象引导)的解决方案的链接显然是错误的。
【问题讨论】:
-
你可以做 MS 对连接点所做的事情:返回调用者提供的 cookie(索引到你的向量中)以注销。
-
我经常将接口指针存储为回调,并将它们放在一个集合中。然后我可以按值访问以取消注册。
-
@RogerRowland 好主意。
-
@WhozCraig Boost 也为他们的一门课程做到了这一点。