首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法为boost::signal 2::signal添加不可复制的连接

无法为boost::signal 2::signal添加不可复制的连接
EN

Stack Overflow用户
提问于 2022-07-01 09:32:19
回答 1查看 48关注 0票数 1

我实现了一个包装器,它允许我完美地将我的处理程序(在本例中是Widget对象)转发到可调用的中,然后我可以使用它作为信号处理程序。

我成功地将处理程序作为元组转发,因此当将lvalue ref作为参数传递以添加函数时,tuple存储对我的对象的引用。在这种情况下,一切看起来都很好。

但是,当我试图按值传递不可复制类的对象时,它会失败。原因是复制构造函数被隐式删除-当然,这是正确的,但我不能真正理解为什么它需要有副本ctor可用?这背后有什么理由吗?还是我的代码中有一个我没有注意到的bug?

编译器资源管理器链接

使用clang 14编译,启用C++20

代码语言:javascript
复制
#include <boost/signals2/signal.hpp>
#include <tuple>
#include <boost/signals2/signal.hpp>
#include <iostream>

struct Widget
{
  Widget() = default;
  Widget(const Widget&) = delete;
  Widget& operator=(const Widget&) = delete;
  Widget(Widget&&) noexcept = default;
  Widget& operator=(Widget&&) noexcept = default;
  ~Widget() noexcept = default;

  void operator()()
  {
    std::cout << "Test\n";
  }
};

struct SigWrapper
{
  boost::signals2::signal<void()> sig;

  template<class Handler>
  void add(Handler&& handler)
  {
    //I need to wrap it here
    auto wrapper = [handler_as_tuple = std::forward_as_tuple(std::forward<Handler>(handler))]() mutable {
      //[...]
      std::invoke(std::get<0>(handler_as_tuple));
    };

    sig.connect(std::move(wrapper));
  }

  void call()
  {
    sig();
  }
};

int main()
{
  auto w = SigWrapper{};
  auto widget = Widget{};
  w.add(widget); //ok: add as lvalue reference, will be wrapped into tuple that will hold ref to Widget
  w.add(Widget{}); //error:
  //copy constructor of '' is implicitly deleted because field '' has a deleted copy constructor

  w.call();
}

/opt/compiler-explorer/libs/boost_1_79_0/boost/signals2/detail/slot_template.hpp:160:26:错误:调用隐式删除的复制构造函数'(lambda在

:29:20)‘/opt/compiler-explorer/libs/boost_1_79_0/boost/signals2/detail/slot_template.hpp:85:9:= detail::get_invocable_slot(f,detail::tag_type(f));^ :34:17:注意:在函数模板专门化的实例化中,sig.connect(std::move(包装));^ :48:5:注意:在函数模板专门化的实例化中,“SigWrapper::add”w.add(Widget{});//error:^ :29:21:注意:“”的复制构造函数被隐式删除,因为“字段”具有已删除的复制构造函数自动包装器= 元组(std::forward(处理程序))可变的{^ /opt/compiler-explorer/gcc-11.2.0/lib/gcc/x86_64-linux-gnu/11.2.0/../../../../include/c++/11.2.0/tuple:744:17:注释:显式默认函数是在这里隐式删除了constexpr (constexpr&)= default;^ /opt/compiler-explorer/gcc-11.2.0/lib/gcc/x86_64-linux-gnu/11.2.0/../../../../include/c++/11.2.0/tuple:599:19:注意:' tuple‘的复制构造函数被隐式删除,因为基类' _Tuple_impl’有一个已删除的复制构造函数类元组: public _Tuple_impl^/_Tuple_impl/编译器-explorer/gcc-11.2.0/lib/gcc/x86_64-linux-gnu/11.2.0/../../../../include/c++/11.2.0/tuple:435:17:注意:显式默认函数在这里被隐式删除,_Tuple_impl(const _Tuple_impl&) = default;^ /opt/compiler-explorer/gcc-11.2.0/lib/gcc/x86_64-linux-gnu/11.2.0/../../../../include/c++/11.2.0/tuple:408:7:注意:“_Tuple_impl”的复制构造函数被隐式删除,因为基类“_Head_base”具有已删除的复制构造函数:_Head_base^/_Head_base/编译器-资源管理器/gcc-11.2.0/lib/gcc/x86_64-linux-gnu/11.2.0/../../../../include/c++/11.2.0/tuple:185:17:注意:显式默认函数在这里被隐式删除,_Head_base(const _Head_base&) = default;^ /opt/compiler-explorer/gcc-11.2.0/lib/gcc/x86_64-linux-gnu/11.2.0/../../../../include/c++/11.2.0/tuple:224:13:注意:“_Head_base”的复制构造函数被隐式删除,因为字段'_M_head_impl‘是rvalue引用类型'Widget &’_Head _M_head_impl;^ /opt/compiler-explorer/libs/boost_1_79_0/boost/function/function_template.hpp:1145:21:注:将参数'f‘传递给这里的参数operator=(函子f) ^

EN

回答 1

Stack Overflow用户

发布于 2022-07-01 10:51:38

Signals2是线程安全的.我认为可复制的要求就是这一结果的结果。例如,在不复制插槽功能的情况下,这种保证似乎很难实现:

注意,即使在断开连接之后,连接的相关插槽也可能仍在执行过程中。换句话说,断开连接不会阻止等待连接的相关插槽完成执行。这种情况可能发生在多线程环境中,如果断开与信号调用同时发生,或者在单线程环境中发生,如果插槽断开自己。

将共享对象转换为可复制对象的常用方法适用(例如使用std::shared_ptr)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72827237

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档