2017-03-04 65 views
1

我有一个QT 5.7项目& Visual Studio 2015发出关于扣减规则的编译器错误。就扣除规则而言,我有点新手,所以我想看看是否有人能告诉我如何解决这个问题,也解释了函数签名匹配到底发生了什么。模板参数扣减不能与QT lambda匹配

我想使用基于模板的智能连接器来管理我的QT项目中的信号和插槽。我从Stack Overflow的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父继承)以拉姆达插槽,但它失败,出现以下错误编译:

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的父QIODevice类继承和签名void bytesWritten(qint64 bytes)

回答

1

更换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*明确是pointer。这个矛盾使编译器无法解析模板。