10 Stimmen

Übergabe von Referenzen an Variadic-Vorlagen

Ich arbeite an einer Ereignisbibliothek und stehe vor einem Problem mit Variadic-Vorlagen.

Alles funktioniert sehr gut, außer der Tatsache, dass ich keine Referenzen als Parameter übergeben kann...

Hier ist ein sehr vereinfachtes Beispiel, das ich geschrieben habe, um mein Problem darzustellen.

struct DelayedSignal 
{   
    ~DelayedSignal ()
    { std::cout << "~DelayedSignal CLOSE" << std::endl; }

    template<class C, class... Args>
    DelayedSignal ( void(C::*func)(Args...), C& obj )
    { std::cout << "DelayedSignal INIT - 03 - pointer to method & pointer to class instance (Arg num: " << sizeof...(Args) << ")" << std::endl; }

    template<class C, class... Args>
    DelayedSignal ( void(C::*func)(Args...), C& obj, Args... args )
    {
        std::cout << "DelayedSignal INIT - 04 - pointer to method & pointer to class instance & arguments (Arg num: " << sizeof...(Args) << ")" << std::endl;
    }
};

template<class... ArgsBis>
struct DelayedSignal_DebugHelper 
{
    ~DelayedSignal_DebugHelper ()
    { std::cout << "~DelayedSignal_DebugHelper CLOSE" << std::endl; }

    template<class C, class... Args>
    DelayedSignal_DebugHelper ( void(C::*func)(Args...), C& obj )
    { std::cout << "DelayedSignal_DebugHelper INIT - 03 - pointer to method & pointer to class instance (Arg num: " << sizeof...(Args) << ")" << std::endl; }

    template<class C, class... Args>
    DelayedSignal_DebugHelper ( void(C::*func)(Args...), C& obj, ArgsBis... args ) // Need to use ArgsBis instead of Args to make it work
    {
        std::cout << "DelayedSignal_DebugHelper INIT - 04 - pointer to method & pointer to class instance & arguments (Arg num: " << sizeof...(Args) << ")" << std::endl;
    }
};

template < class Tr, class... Args >
struct Signal
{
    void fire ( Args... args ) { std::cout << "Signal::fire::" << sizeof...(Args) << std::endl; }
};

struct Klass {};

int main()
{
    std::string str1("Blop");   // Will be used as reference
    Klass k;                    // Will be used as reference

    Signal<void, Klass&> signal_01;
    Signal<void, std::string&> signal_02;

    std::cout << "====== DelayedSignal :: needed for production purpose ===============" << std::endl;

    // OK
    DelayedSignal test01(&Signal<void, std::string&>::fire, signal_02);
    // HERE IS THE PROBLEM
    //DelayedSignal test02(&Signal<void, std::string&>::fire, signal_02, str1);

    // OK
    DelayedSignal test03(&Signal<void, Klass&>::fire, signal_01);
    // HERE IS THE PROBLEM
    //DelayedSignal test04(&Signal<void, Klass&>::fire, signal_01, k);

    std::cout << "====== DelayedSignal_DebugHelper :: used only for debug purpose ======" << std::endl;

    // OK
    DelayedSignal_DebugHelper<std::string&> test05(&Signal<void, std::string&>::fire, signal_02);
    // OK
    DelayedSignal_DebugHelper<std::string&> test06(&Signal<void, std::string&>::fire, signal_02, str1);

    // OK
    DelayedSignal_DebugHelper<Klass&> test07(&Signal<void, Klass&>::fire, signal_01);
    // OK
    DelayedSignal_DebugHelper<Klass&> test08(&Signal<void, Klass&>::fire, signal_01, k);

    return 1;
}

Da ich alle DelayedSignal-Instanzen in einer einzigen std::list-Instanz registriere, möchte ich die Verwendung von Vorlagen für die Klasse selbst vermeiden, und deshalb verwende ich stattdessen Vorlagen für die Konstruktoren. Ich könnte auch eine rein virtuelle Klasse als Basis für alle DelayedSignal verwenden und Zeiger auf die virtuelle Klasse in der std::list registrieren, aber ich denke, es ist am besten, die Verwendung von virtuellen Methoden zu minimieren, und ich bin wirklich von diesem Problem fasziniert...

Wie Sie in diesem Beispiel sehen können, geben test02 und test04 Fehler zurück, wenn sie aktiviert sind. DelayedSignal_DebugHelper ist fast identisch mit DelayedSignal, mit der Ausnahme, dass es ArgsBis (ein Klassenvorlagenargument) im letzten Konstruktor anstelle der Args-Vorlage (das Methodenvorlagenargument) verwendet, sonst funktioniert es nicht (wie bei DelayedSignal). Args wird akzeptiert auf der void(C::*func)(Args...) ist aber nicht mit ArgsBis... args obwohl sie in derselben Konstruktordeklaration enthalten sind.

Soweit ich weiß, gibt es kein Problem ohne Referenzen ( DelayedSignal test04(&Signal<void, Klass>::fire, signal_01, k); zum Beispiel) oder mit mehreren Parametern (oder ohne), solange es keine Referenzen gibt.

Gibt es eine Möglichkeit, dieses Problem zu beheben?

Ich danke Ihnen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X