2017-03-04 124 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。這個矛盾使編譯器無法解析模板。