【问题标题】:std::function as key in associative containersstd::function 作为关联容器中的键
【发布时间】:2020-05-18 11:37:58
【问题描述】:

我的理解是否正确,不能使用std::function 作为既没有有序的键,即std::mapstd::set,也没有无序的关联容器,即std::unordered_mapstd::unordered_set

背景是我实现了一个计时器驱动的观察者,即本例中的主题。我给观察者一个std::function<void(void)> 对象以便再次取消订阅。当然,当这个取消订阅函数被调用时,主题必须保持哪些回调应该被取消/删除。

我很自然地考虑使用std::function 的副本作为std::mapstd::unordered_map 的键。希望函数指针类似于语义,我希望相等运算符,std::function 实例化的 less 或 hash 实现。我在阅读参考资料/标准时遇到的莫名其妙的事情是:operator==operator!= 没有按预期工作,因为它们仅与空的即默认构造的函数对象进行比较。

但是,当我阅读 23.14.7 和我的一般理解时,我应该能够在上述容器中使用开箱即用的 std::function 实例化,因为它们使用 std::equal_to 而不是直接使用 == 对吗?

身份,即std::equal_to/total 顺序将匹配两个“指向”相同回调的函数对象,对吧?

【问题讨论】:

  • 我认为std::equal_to 无论如何都会使用默认的==,并且由于== 仅适用于std::nullptr_t 类型,因此您不能按照您的描述进行操作。
  • @Superlokkus 你在哪里看到这样的东西?我在 func.wrap.func 中找不到任何这些(哈希、减和算术运算符)。

标签: c++ c++17 std-function


【解决方案1】:

背景是我实现了一个计时器驱动的观察者,即本例中的主题。我给观察者一个 std::function 对象以便再次取消订阅。

不要那样做。

相反,将迭代器返回到您存储订阅者可用于取消订阅的函数对象的容器。


我应该能够在上述容器中使用开箱即用的 std::function 实例化,因为它们使用 std::equal_to 而不是直接 == 对吗?

通用std::equal_to 直接使用运算符==std::function 没有专业化。因此在std::function 的情况下使用==std::equal_to 没有区别。

总结:std::function 不能用作关联容器中的键。而且也没有合理的方法让它与自定义比较函数一起使用。


该死,为什么 std::function 还要实现一个 std::hash,一个总顺序保证更少的运算符甚至算术运算符?

std::function 没有实现其中任何一个。

【讨论】:

  • 这不是直接可行的,因为我必须翻译调用者的线程/生命周期/同步边界,即我的主题使用 boost::asio 和自己的线程运行,而调用者正在尝试取消订阅从 Qt GUI 线程,或通过 NAPI 从 javascript GUI 线程,加上 boost::asio::strand 上的同步。
  • @Superlokkus 不清楚如何使用std::function 作为密钥来解决这个问题。
  • 只是为了看家,我可以省略一个id。
  • 但是,请将您的答案集中在在 ass 中使用 std::function 的一般问题上。容器。似乎答案是否定的,无法使用它们,尽管这样的代码格式正确,但它将无法使用。
  • 为了给你一个更好的画面:取消订阅回调/函数对象当然会包含首先同步实际取消订阅的指令,即只需使用给定的链发布包含的 io_context,这会删除内部容器中的观察回调。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-19
  • 1970-01-01
  • 2020-03-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多