首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >信号槽语法糖

信号槽语法糖
EN

Stack Overflow用户
提问于 2015-02-08 19:25:29
回答 2查看 323关注 0票数 3

最近,我在互联网上搜索好的信号插槽库,想知道为什么在连接成员方法到信号时,我们到底为什么需要这么麻烦的语法?

通常我们必须写这样的东西:

代码语言:javascript
复制
mySignal.connect(&MyClassName::myMethodName, this);

或者像这样:

代码语言:javascript
复制
mySignal += std::bind(&MyClassName::myMethodName, this, std::placeholders::_1);

有明显的重复和不必要的打字。在现代C++中,是否有可能以例如C#的方式实现这些功能:

代码语言:javascript
复制
mySignal += myMethodName

并从上下文中自动捕获指向成员函数的指针和这个指针?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-02-08 19:39:38

在现代C++中,是否有可能以C#的方式实现这样的功能?

不,这在C++中是不可能的。获取成员函数地址的语法要求用类名(即&MyClassName::myMethodName)对函数名进行限定。

如果不想指定类名,一种可能是使用lambdas。特别是,如果您能够负担得起C++14编译器,那么泛型lambda允许编写:

代码语言:javascript
复制
mySignal.connect([this] (auto x) -> { myMethodName(x) });

可悲的是,你不能比这简单多了。您可以使用默认lambda捕获来保存一些语法噪音:

代码语言:javascript
复制
mySignal.connect([&] (auto x) -> { myMethodName(x) });

然而,Scott在他的新书“有效的现代C++”中对默认的lambda捕获模式的缺陷提出了警告。从可读性的角度来看,与第一个选项相比,我不确定这会改善很多事情。

此外,如果您希望lambda将其论点完美地转发给myMethodName,事情很快就会变得尴尬起来。

代码语言:javascript
复制
mySignal.connect([&] (auto&& x) -> { myMethodName(std::forward<decltype(x)>(x)) });

如果您不介意宏(我通常这样做),您可以使用基于预处理的解决方案as suggested by Quentin in their answer。但是,在这种情况下,我更喜欢使用完美转发lambda:

代码语言:javascript
复制
#define SLOT(name) \
        [this] (auto&&... args) { name (std::forward<decltype(args)>(args)...); }

你可以这样用:

代码语言:javascript
复制
e.connect(SLOT(foo));

这是一个http://coliru.stacked-crooked.com/a/2d5ff31eab8cd993

票数 6
EN

Stack Overflow用户

发布于 2015-02-08 19:46:29

预处理器应该试一试吗?

代码语言:javascript
复制
#include <type_traits>
#define CONNECT(method) \
    connect(&std::remove_pointer_t<decltype(this)>::method, this)

拐杖的用途如下:

代码语言:javascript
复制
mySignal.CONNECT(myMethodName);
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28398309

复制
相关文章

相似问题

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