【问题标题】:C++ std::list with std::function: calling remove() won't build带有 std::function 的 C++ std::list:调用 remove() 不会构建
【发布时间】:2021-05-18 08:46:37
【问题描述】:

谁能解释一下为什么这段代码不能编译:

std::function<void(int)> intcb = [](int a)
{
    std::cout << "callback: " << a << std::endl;
};

std::list<std::function<void(int)>> list;
list.push_back(intcb);
list.remove(intcb);

构建错误位于删除函数中:

no match for 'operator==' (operand types are 'std::function<void(int)>' and 'const value_type' {aka 'const std::function<void(int)>'})

感谢您的帮助

【问题讨论】:

  • 该解决方案是否应该适用于带有捕获的 lambda?如果你不需要有状态的函数,你可以使用普通函数指针。
  • 作为一种更简单但更昂贵的替代方案,您可以考虑将函数存储在 std::unordered_map&lt;tag_t,std::function&lt;void(int)&gt; 中,以便您可以根据某些标签删除它们。
  • std::functions 不能使用 == 相互比较。但是您可以为它制作自己的可比较的包装器。示例:stackoverflow.com/a/53462084/2752075
  • 目前我认为std::unordered_map 的想法是最好的解决方案......我会尝试这样:-) 感谢大家的帮助
  • 是否需要按一定的顺序执行回调?否则你可以使用pop_back()pop_front()

标签: c++ stl


【解决方案1】:

好吧,您想创建一个函数列表,然后启用“删除”功能,但是对于删除操作,列表需要能够比较其类型的实例,因为它不依赖于对对象的引用。

所以你需要为你指定的函数类型定义operator==

【讨论】:

  • 感谢您的快速回复。为模板化 std::function 实现此类运算符的最佳方法是什么?
  • 你可以使用std::list&lt;std::function&lt;void(int)&gt;*&gt; list; list.push_back(&amp;intcb); list.remove(&amp;intcb); 虽然这有点老套......
  • 谢谢@Den-Jason。这个解决方案在我看来有点“老派” :-D 但如果没有更好的解决方案,我会这样做。
  • @Kill_Switch 只是要小心指针,因为你需要确保原来的intcb 从插入到移除都是活着的,即问题出现了:为什么把它放在列表中首先,无论如何您需要将原始活动与列表分开
  • @largest_prime_is_463035818 你完全正确,使用老式指针的东西可能很危险。何时调用 push_back() 我只会引用位于调用者堆栈上的临时 std::function 对象...
【解决方案2】:

这是否有意义:您在列表中拥有的是函数对象,而当您将其放入列表时,您实际上是在复制 intcb。因此,您需要一种比较副本的方法。相反,您可以尝试通过指针存储,因此可以通过比较开箱即用的地址来删除。

#include <iostream>
#include <list>
#include <functional>

std::function<void(int)> intcb = [](int a)
{
    std::cout << "callback: " << a << std::endl;
};


int main() {
    std::list<std::function<void(int)>*> list;
    list.push_back(&intcb);
    list.remove(&intcb);
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-19
    相关资源
    最近更新 更多