最近,我在互联网上搜索好的信号插槽库,想知道为什么在连接成员方法到信号时,我们到底为什么需要这么麻烦的语法?
通常我们必须写这样的东西:
mySignal.connect(&MyClassName::myMethodName, this);或者像这样:
mySignal += std::bind(&MyClassName::myMethodName, this, std::placeholders::_1);有明显的重复和不必要的打字。在现代C++中,是否有可能以例如C#的方式实现这些功能:
mySignal += myMethodName并从上下文中自动捕获指向成员函数的指针和这个指针?
发布于 2015-02-08 19:39:38
在现代C++中,是否有可能以C#的方式实现这样的功能?
不,这在C++中是不可能的。获取成员函数地址的语法要求用类名(即&MyClassName::myMethodName)对函数名进行限定。
如果不想指定类名,一种可能是使用lambdas。特别是,如果您能够负担得起C++14编译器,那么泛型lambda允许编写:
mySignal.connect([this] (auto x) -> { myMethodName(x) });可悲的是,你不能比这简单多了。您可以使用默认lambda捕获来保存一些语法噪音:
mySignal.connect([&] (auto x) -> { myMethodName(x) });然而,Scott在他的新书“有效的现代C++”中对默认的lambda捕获模式的缺陷提出了警告。从可读性的角度来看,与第一个选项相比,我不确定这会改善很多事情。
此外,如果您希望lambda将其论点完美地转发给myMethodName,事情很快就会变得尴尬起来。
mySignal.connect([&] (auto&& x) -> { myMethodName(std::forward<decltype(x)>(x)) });如果您不介意宏(我通常这样做),您可以使用基于预处理的解决方案as suggested by Quentin in their answer。但是,在这种情况下,我更喜欢使用完美转发lambda:
#define SLOT(name) \
[this] (auto&&... args) { name (std::forward<decltype(args)>(args)...); }你可以这样用:
e.connect(SLOT(foo));这是一个http://coliru.stacked-crooked.com/a/2d5ff31eab8cd993。
发布于 2015-02-08 19:46:29
预处理器应该试一试吗?
#include <type_traits>
#define CONNECT(method) \
connect(&std::remove_pointer_t<decltype(this)>::method, this)拐杖的用途如下:
mySignal.CONNECT(myMethodName);https://stackoverflow.com/questions/28398309
复制相似问题