2017-04-27 18 views
0

是否有可能創建可變參數信號連接通用lambda作爲插槽?我的意思是這樣(比如,在需要的參與功能,所有的定義可見(例如,在實例化點)):可變參數信號和通用的Lambda表達式

#include <QCoreApplication> 
#include <QObject> 
#include <QTime> 

class A 
    : public QObject 
{ 
    Q_OBJECT 

public : 

    A(QObject * const parent = Q_NULLPTR) 
     : QObject{parent} 
    { ; } 

signals : 

    template< typename ...Ts > 
    void infoMessage(Ts... args); 

public slots : 

    void run() 
    { 
     emit infoMessage("Started at ", QTime::currentTime()); 
    } 

}; 

#include <QTimer> 
#include <QtDebug> 

#include "main.moc" 

int main(int argc, char * argv []) 
{ 
    QCoreApplication a{argc, argv}; 
    A a; 
    auto printInfoMessage = [&] (auto... args) 
    { 
     (qInfo() << ... << args); 
    }; 
    QObject::connect(&a, SIGNAL(infoMessage), printInfoMessage); 
    QTimer::singleShot(0, &a, &A::run); 
    return a.exec(); 
} 

目前,它給出了一個錯誤信息:

AUTOGEN: error: process for main.cpp:18: Error: Template function as signal or slot

moc failed...

這裏宏SLOT()代替&A::infoMessage幫助不大。有沒有解決這個限制的解決方法?

我知道,一些答案將包含使用std::make_tuplestd::index_sequence東西。但是有沒有更詳細的解決方案?

回答

1

有模板沒有直接的解決方法。原因在於moc索引所有信號和插槽,並且功能模板無法完成此功能,因爲功能模板將根據通常無法從moc訪問的代碼生成多個功能。

我不認爲你可以使它與元組一起工作,例如這些也是模板。

解決方案可能是使用QVariant和/或QVariantList作爲參數。


請注意,錯誤不是由QObject::connect線造成的,但在A級的信號聲明

而且,你不能在你的意志代替SIGNAL()SLOT(),它要麼是一個信號一個插槽,它不能同時存在。

最後,你應該使用這種形式:

QObject::connect(&a, &A::infoMessage, printInfoMessage); 

而且,由於printInfoMessage使用自動參數,您可能需要強制使用qOverload自動分辨率:

QObject::connect(&a, &A::infoMessage, qOverload<QVariantList>(printInfoMessage)); 
+0

難道就沒有可能收集'發出someSignal(...);'點上的成員函數實例化的所有變種,然後在連接之前生成所有相應的特化項? – Orient

+0

不。編譯完成之前調用'moc',並且只處理具有Q_OBJECT宏的文件。 moc的輸出是在編譯自己的C++文件的同時編譯的C++代碼。所以鏈接時間對於moc添加任何功能來說已經太晚了。但是,鏈接時間現在還不知道模板函數的任何用例(例如,您是在構建一個庫,使用您的庫的二進制文件將根據您的模板生成自己的函數) –

+0

您認爲:是當靜態反射變爲可用時可以克服所有這些限制嗎?或者'clang'基礎設施的某些部分可以在這裏幫助? – Orient