我尝试使用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":未声明的标识符
感谢您的帮助
答案1:
您文章中的RREvent1Arg
不是通用的信号/插槽系统。它不是以一种笼统的方式写的。它没有被编写为适应void
也就不足为奇了,就像它不处理除1(给定名称)之外的许多参数也就不足为奇一样。
请注意,它将回调处理程序定义为typedef std::function<void (T1)> 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
的捕捉是一种很好的风格。似乎在其他问题上给人们带来了问题。
我写了这个"简单信号库",用于一系列项目:
http://bitbucket.org/danielko/simplesignal
它不处理返回值的累积,因为我认为这个用例不够常见,不足以保证额外的复杂性。
不过,它所实现的是信号/插槽语义;当你连接时,你会得到一个插槽,只要你想从信号中接收通知,你就需要保持它的活动状态。销毁插槽(或在插槽上调用disconnect()
)将停止向插槽所有者传递信号。
希望它足够简单易懂;可变模板可以处理任意数量的参数,不需要专门化。