2017-04-27 3 views
0

Ist es möglich, variadische Signal und verbinden generic Lambda als Slot zu schaffen? Ich meine, so etwas wie (sagen wir, alle Definitionen der beteiligten Funktionen sichtbar sind, wo erforderlich (zB an den Punkten der Instanziierung)):Variadische Signale und allgemeine lambdas

#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(); 
} 

Derzeit gibt es eine Fehlermeldung:

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

moc failed...

Hier Makro SLOT() statt von &A::infoMessage hilft nicht viel. Gibt es Workarounds, um diese Einschränkung zu überwinden?

Ich weiß, dass einige der Antworten eine Verwendung von std::make_tuple und std::index_sequence Zeug enthalten werden. Aber gibt es weniger ausführliche Lösung?

Antwort

1

Es gibt keine direkte Problemumgehung für die Vorlage. Ein Grund dafür ist, dass der Moc alle Signale und Slots indiziert, und dies kann nicht für Funktionsschablonen durchgeführt werden, da Funktionsschablonen abhängig vom Code mehrere Funktionen generieren, auf die das Moc im Allgemeinen nicht zugreifen kann.

Ich glaube nicht, dass Sie es mit Tuple arbeiten können und solche wie diese auch Vorlagen sind.

Eine Lösung könnte sein, QVariant und/oder QVariantList für Ihre Argumente zu verwenden.


Bitte beachten Sie, dass der Fehler nicht durch die QObject::connect Leitung verursacht wird, aber die die Signaldeklaration in der Klasse A.

Außerdem können Sie SIGNAL() und SLOT() an Ihrem Willen nicht ersetzen, ist es entweder ein Signal oder ein Steckplatz, es kann nicht beides sein.

Und schließlich sollten Sie dieses Formular verwenden:

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

Und da printInfoMessage wird auto-Parameter verwenden, müssen Sie möglicherweise die automatische Auflösung zwingen müssen mit qOverload:

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

Ist es nicht möglich, um alle Varianten der Instanziierung der Elementfunktion auf 'emit someSignal (...);' Punkten zu sammeln und dann alle entsprechenden Spezialisierungen direkt vor dem Verknüpfen zu generieren? – Orient

+0

Nein. Das 'moc' wird vor jeder Kompilierung aufgerufen und verarbeitet nur Dateien mit dem Makro Q_OBJECT. Die Ausgabe von moc ist C++ - Code, der zur gleichen Zeit kompiliert wird, wenn Ihre eigenen C++ - Dateien kompiliert werden. Die Verbindungszeit ist also viel zu spät für den Moc, um irgendeine Funktion hinzuzufügen. Die Link-Zeit ist aber auch viel zu früh, um irgendwelche Anwendungsfälle Ihrer Template-Funktion zu kennen (zB wenn Sie eine Library erstellen, die Binärdatei, die Ihre Library verwendet, generiert eigene Funktionen basierend auf Ihrer Vorlage) –

+0

Was denken Sie: ist Ist es möglich, all diese Einschränkungen zu überwinden, wenn statische Reflexion verfügbar wurde? Oder vielleicht können einige Teile der "Clang" -Infrastruktur hier helfen? – Orient