【问题标题】:c++11 Signal systemc++11信号系统
【发布时间】:2013-12-14 03:24:32
【问题描述】:

我尝试在 C++ 11 中使用“简单”信号系统。我使用以下类: http://geekswithblogs.net/raccoon_tim/archive/2011/09/28/lambdas-and-events-in-c.aspx

但我有一个问题(我使用 Visual Studio 2012):

问题描述

我无法创建这样的活动:

RREvent1Arg<void> testEvent;

“void”不是参数类型!!

我尝试过“模板专业化”,例如:

template<typename T1, typename T2> class Signaler {};
template<> class Signaler<T1> {};
template<> class Signaler<void> {};

但是我遇到了一些编译问题:

错误 C2065:“T1”:未声明的标识符

感谢您的帮助

【问题讨论】:

  • 向我们展示一些我们可以尝试编译的代码。
  • 除非您已经致力于这个“简单”的信号系统,否则我建议您使用更普遍(经过试验和测试)的库,例如 boost signals2。
  • 我已经解决了问题 2,这是一个“完全重新编译”问题!感谢您的 cmets...
  • Here is a signals system 我刚刚写的。我很无聊。
  • 非常感谢,问题是VS2012不支持可变参数模板:-(

标签: c++ events c++11 lambda signals


【解决方案1】:

答案 1:

您文章中的这个RREvent1Arg 不是通用信号/插槽系统。它不是以一般化的方式编写的。它没有被编写来容纳void 并不奇怪,正如它不处理除 1 之外的许多参数(给定名称)也就不足为奇了。

请注意,它将回调处理程序定义为typedef std::function&lt;void (T1)&gt; Func;,然后尝试定义void Call( T1 arg ) 之类的东西。您不能在 C++ 中的 void foo( void arg ) 之类的源代码中声明函数,并且模板也不允许创建这些函数。有一些方法可以使用重载来解决这个问题,但也有一些方法可以使用可变参数等。

答案 2:

顺便说一句,我不确定在“this”上使用 lambda 的捕获功能的规则是什么,尤其是当它被包装为 std::function 时。而且因为它令人困惑,我建议将其保存到另一个局部变量中,并按值捕获:

static RREvent1Arg<int> testEvent;
class MyClass
{
 int a;
 void MyMethod()
 {
   MyClass *mc = this;
   testEvent += [=mc](int) { mc->SignalReceived(); };
 }

 void SignalReceived()
 {
   this->a = 10;
 }
};

但这只是我。也许this 捕获是很好的风格。似乎会给其他问题的人带来问题。

【讨论】:

  • 仅供参考,您可以在 lambda 中捕获 this,但它只能通过值捕获,而不是通过引用捕获。最大的风险是您必须保证至少只要 lambda 仍然存在,指针仍然有效。
  • 感谢 HostileFork,我同意你的观点,我的目标是稍微改进它。第一步是处理“void”,然后处理几个参数......但两者都不知道如何处理?
  • @Spectral 如果你真的想编写一个信号槽库,会有很多方法来攻击它。如果你想走RREvent&lt;&gt; 和RREvent&lt;int&gt; 和RREvent&lt;int, int&gt; 的路,你可以看看variadic templates。你也可以定义一个函数类型,然后设计你的信号槽机制来参数化。可能最好先研究和使用其他人设计的东西,不过......
  • 是的,但是 Visual Studio 2012 不支持可变参数模板 :-(
  • @Spectral 您应该提出一个新问题,而不是进行使现有答案似乎没有意义的编辑。作为一个新问题提出这个问题,然后roll back the question in the history 到版本 4。(有一个“回滚”按钮)。
【解决方案2】:

我编写了这个“简单的信号库”,用于一堆项目:

http://bitbucket.org/danielko/simplesignal

它不处理返回值的累积,因为我认为该用例不够普遍,不足以保证额外的复杂性。

它实现的是信号/槽语义;当你连接时,你会得到一个插槽,只要你想接收来自信号的通知,你就需要保持活动状态。销毁槽(或在其上调用disconnect())将停止将信号传递给槽的所有者。

希望它足够简单易读,易于理解;可变参数模板处理任意数量的参数,无需专门化。

【讨论】:

  • 非常感谢 Daniel,问题是它不能用 Visual Studio 2012 编译。不支持可变参数模板!
猜你喜欢
  • 1970-01-01
  • 2020-02-16
  • 2014-09-10
  • 2012-08-22
  • 2017-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多