用C ++ 11信号替换boost-signals2

And*_*ard 2 c++ boost signals boost-signals2

我是一名研究人员,为无人驾驶汽车开发自动驾驶系统,并且正在修改另一个项目的一些开源代码,以制造用于车辆控制的驱动程序。这个想法是要有一个模块,该模块通常处理将特定于车辆的驾驶员加载为库的控制,并且现有实现使用boost :: signals2将模块函数调用绑定到驾驶员。因为这是当前唯一用于boost的东西,所以我想删除boost依赖并使用C ++信号,但是我很难弄清楚该怎么做。

我一直在尝试阅读boost :: signals2和C ++信号,以了解自己是否可以自学原理和语法:-https: //en.cppreference.com/w/cpp/utility/program/信号 - https://testbit.eu/2013/cpp11-signal-system-performance - https://simmesimme.github.io/tutorials/2015/09/20/signal-slot 我觉得我得到的概念,但是实现使tar混乱了。我发布的第一个和第二个资源使它看起来像C ++信号内置在C ++ 11中,但是第三个链接中的教程似乎定义了自己的信号类,并且似乎没有在第一个中使用语法所有。

看来其他项目之前(https://github.com/cinder/Cinder/issues/619)都已完成此操作,但我无法找到任何具体的示例来说明前后的比较-看到一个实现通常是使理论对我有效的方法。

从驱动程序库头文件中:

class InterfaceBase
{
   InterfaceBase( const Config& cfg );
   virtual ~InterfaceBase() { }

   boost::signals2::signal<void (const InterfaceState& state)> signal_state_change;
}
Run Code Online (Sandbox Code Playgroud)

从驱动程序cpp文件中:

void InterfaceBase::check_change_state()
{
   if( state_ != previous_state )
   {
      signal_state_change( state_ );
   }
}
Run Code Online (Sandbox Code Playgroud)

从模块cpp中:

template<typename Signal, typename Slot>
   void connect( Signal* signal, Slot slot )
{ signal->connect( slot ); }

template<typename Signal, typename Obj, typename A1>
   void connect( Signal* signal, Obj* obj, void( Obj::*mem_func )( A1 ))
{ connect( signal, boost::bind( mem_func, obj, _1 )); }

Interface::Interface()
{
   if( cfg_.has_driver_lib_path() )
   {
      driver_library_handle = dlopen( cfg_.driver_lib_path().c_str(), RTLD_LAZY );
      if( !driver_library_handle )
      {
         exit( EXIT FAILURE );
      }
   }
   else
   {
      exit( EXIT_FAILURE );
   }
   driver_ = load_driver( &cfg_ );

   connect( &driver_->signal_state_change, this, &Interface::ProcessStateChange );
}
Run Code Online (Sandbox Code Playgroud)

驱动程序声明一个信号,可用于将数据发送到加载它的模块,然后该模块将该信号绑定到一个函数,以便在调用该信号并将数据提供给该函数时,数据将转到该函数。我只是想弄清楚如何在不使用Boost的情况下完成同样的事情,我想这意味着还要弄清楚如何替换boost :: bind。任何朝着正确方向的指点都会受到赞赏;我将继续努力,并在我发现其他问题时发布,以防将来对走同一条路的人有所帮助。

met*_*tal 7

这里的问题是,有两种相关但不同的技术都被称为信号。

信号构成<signal.h>及与之对应的<csignal>POSIX意义上的信号,并且与错误处理(例如,当OS终止程序或发生灾难性的内部错误时)相关。

信号和插槽(例如Boost.signals2,Qt的信号/插槽等)是观察者模式的更一般的实现,它允许一段代码为另一段代码提供松散耦合的方式,以便在某些代码获得通知或回调时事件发生。

前者实际上是后者的子集,因为POSIX信号主要与错误和终止事件有关,而信号和插槽通常也可用于不太有害的事件,例如“网络数据包到达!”。或“用户单击了按钮!”

我不建议尝试将通用的信号插槽解决方案塞入陈旧(和C风格)的POSIX信号API中。

虽然没有标准的C ++信号/插槽库,但是有一些第三方库,如您的某些链接所示。除非您有充分的理由重新发明轮子,否则我不建议自己动手做。(如果必须自己动手,那将std::function是一个明显的起点。)Boost's是高质量的实现,并且由于您已经在使用它,因此我会坚持这样做。(在我公司的经验法则是,在所有条件大致相等的情况下,“ std> Boost> Qt> other”,但YMMV。)

如果您只想减少Boost文件夹的占用空间,则Boost会提供BCP来做到这一点。

  • @Ruslan Boost 实际上并不是一个单一的库,而是一个库的集合,它们具有不同程度的实用性和质量(但它们是经过精心策划的,所以它们都不是完全糟糕的)。指出 Boost.Units 中的一个特定错误(这是 Boost 中相对模糊的部分)并没有说明任何关于 Boost.Signals2 的事情。 (2认同)