c++ - 模板参数推导与 QT lambda 不匹配

标签 c++ qt lambda template-argument-deduction

我有一个使用 QT 5.7 和 Visual Studio 2015 的项目,该项目发出关于推导规则的编译器错误。就推导规则而言,我还是个新手,所以我想看看是否有人可以告诉我如何解决这个问题,并解释函数签名匹配的进展情况。

我正在尝试使用基于模板的智能连接器来管理我的 QT 项目中的信号和插槽。我从 this Q&A 获得了这种信号/插槽管理方法的灵感在堆栈溢出中。自动管理信号/槽的模板代码如下:

//! see https://stackoverflow.com/questions/26553029/
//! how-to-disconnect-a-lambda-function-without-storing-connection.
using ListenToken = std::shared_ptr<void>;

struct Disconnecter {
    QMetaObject::Connection mConnection;
    explicit Disconnecter(QMetaObject::Connection&& conn)
        : mConnection(std::move(conn))
    {}

    ~Disconnecter() {
        QObject::disconnect(mConnection);
    }
};

template<class F, class T, class M>
ListenToken QtConnect(T* source, M* method, F&& f) {
    return std::make_shared<Disconnecter>(
        QObject::connect(source, method, std::forward<F>(f))
    );
}

using SignalSlotInfo = std::vector<ListenToken>;

在我的主窗口类中,我有一个 SignalSlotInfo我用来跟踪信号/槽的成员,以便在发生某些 UI 事件的应用程序关闭时,它们可以自动断开连接。

我试图连接的 QT 对象是 QSerialPort。我正在尝试将 QSerialPort 的“字节写入”信号(继承自其 QIODevice 父级)连接到 lambda 中的插槽,但它无法编译并出现以下错误:

1>mainwindow.cpp(1246): error C2672: 'QtConnect': no matching overloaded function found
1>mainwindow.cpp(1246): error C2784: 'ListenToken QtConnect(T *,M *,F &&)': could not deduce template argument for 'M *' from 'void (__cdecl QIODevice::* )(qint64)'
1>  c:\users\johnc\main\app739\app739\mainwindow.h(58): note: see declaration of 'QtConnect'

如果我尝试在不使用 lambda 的情况下执行此操作(使用 QT connect 调用),它可以正常工作......

// Connect Tx/Rx handlers
connect(mPort.get(), &QSerialPort::bytesWritten, this, &MainWindow::processTx);

但是调用 mainwindow.cpp 中的 QtConnect 模板如下:

// Connect Tx/Rx handlers
QtConnect(mPort.get(), &QSerialPort::bytesWritten, [&](qint64 bytes) {
    ...
});

导致上述错误。 mPort是一个指针 std::unique_ptr<QSerialPort>

bytesWritten signal继承自QSerialPort的父类QIODevice并有签名void bytesWritten(qint64 bytes)

最佳答案

M*替换为M:

template<class F, class T, class M>
ListenToken QtConnect(T* source, M method, F&& f) {
    return std::make_shared<Disconnecter>(
        QObject::connect(source, method, std::forward<F>(f))
    );
}

这背后的原因是,如果您保留 M*,编译器将尝试通过将 M* 设置为 void (QIODevice::*)(qint64)。但是 void (QIODevice::*)(qint64) 是一个 pointer-to-member,而不是 pointerM* 明确地是一个指针。这种矛盾导致编译器无法解析模板。

关于c++ - 模板参数推导与 QT lambda 不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42600771/

相关文章:

c++ - 如何将 lambda 用于 std::find_if

c++ - 调用函数后程序忽略所有内容

c++ - 使用 F5 虚拟 ip 和 C++ 连接 IBM MQ 队列

c++ - 需要一致的调试常量来触发所有平台上的操作

java - 项目列表的属性只有一个字节[],

java - 捕获在 lambda 中抛出的 RuntimeException 并在检查时重新抛出它

c++ - boost 可选和用户定义的转换

c++ - 为什么我的代码在调用免费电话时会崩溃?

c++ - 显示 mp3 文件,但使用 QFileDialog 选择文件夹

c++ - 使用 C++11 编译 ui 代码时遇到 "unable to find string literal operator"错误