模板参数推导与 QT lambda 不匹配
Template Argument deduction fails to match with QT lambda
我有一个使用 QT 5.7 和 Visual Studio 2015 的项目,它发出关于推导规则的编译器错误。就推导规则而言,我有点新手,所以我想看看是否有人可以告诉我如何解决这个问题,并解释函数签名匹配的进展情况。
我正在尝试使用基于模板的智能连接器来管理我的 QT 项目中的信号和插槽。我从 Stack Overflow 中的 this Q&A 获得了这种 signal/slot 管理方法的灵感。自动管理signal/slot的模板代码如下:
//! see
//! 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>;
在我的主窗口 class 中,我有一个 SignalSlotInfo
成员,我用它来跟踪 signal/slot,这样当应用程序关闭某些 UI 事件发生。
我试图连接的 QT 对象是 QSerialPort。我正在尝试将 QSerialPort 的 'bytes written' 信号(继承自其 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 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
信号继承自 QSerialPort 的父级 class 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
,而不是 pointer
,而 M*
明确是 pointer
。这种矛盾导致编译器无法解析模板。
我有一个使用 QT 5.7 和 Visual Studio 2015 的项目,它发出关于推导规则的编译器错误。就推导规则而言,我有点新手,所以我想看看是否有人可以告诉我如何解决这个问题,并解释函数签名匹配的进展情况。
我正在尝试使用基于模板的智能连接器来管理我的 QT 项目中的信号和插槽。我从 Stack Overflow 中的 this Q&A 获得了这种 signal/slot 管理方法的灵感。自动管理signal/slot的模板代码如下:
//! see
//! 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>;
在我的主窗口 class 中,我有一个 SignalSlotInfo
成员,我用它来跟踪 signal/slot,这样当应用程序关闭某些 UI 事件发生。
我试图连接的 QT 对象是 QSerialPort。我正在尝试将 QSerialPort 的 'bytes written' 信号(继承自其 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 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
信号继承自 QSerialPort 的父级 class 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
,而不是 pointer
,而 M*
明确是 pointer
。这种矛盾导致编译器无法解析模板。