2014-11-18 21 views
6

Ich habe folgende C++ 11 Beispiel, in dem ich habe eine Funktion, die call variadische Vorlagen zu akzeptieren und rufen eine generische Klasse-Methode verwendet:inkonsistente Parameter Pack Abzug mit variadische Vorlagen

#include <utility> 

template <typename T, typename R, typename... Args> 
R call(R (T::*fn)(Args...), T *t, Args&&... args) { 
    return ((*t).*fn)(std::forward<Args>(args)...);  
} 

class Calculator { 
    public: 
    int add(const int& a, const int& b) { 
     return a + b; 
    } 
}; 

int main() { 
    Calculator *calculator = new Calculator(); 
    int* a = new int(2);  
    int* b = new int(4); 

    // compiles 
    int res1 = calculator->add(*a, *b);  

    // does not compile! 
    int res2 = call<Calculator>(&Calculator::add,calculator, *a, *b);  

    return 0; 
} 

Wie im Code kommentiert Ich bin nicht in der Lage, eine int zu übergeben, wenn die Funktion const int annehmen, während in der Richtung Methodenaufruf kann ich. Ich erhalte den folgenden Kompilierungsfehler:

Wird die C++ - Variadic-Vorlage im Vergleich zur regulären Ausführung strenger Typprüfung unterzogen? Ich bin mit g ++ 4.8.1 mit C++ 11.

+0

Vielleicht mögen Sie Clang die Fehler besser: * Anmerkung: Kandidat Vorlage ignoriert: widersprüchliche Typen für Parameter 'Args' abgeleitet ( vs. ) * – chris

+0

Bedeutet das, dass die Typen genau übereinstimmen müssen, wenn variadische Vorlagen verwendet werden? – jeffreyveon

+1

Es bedeutet, dass Sie verschiedene Typen für den gleichen Template-Parameter nicht ableiten können, weil der Compiler nicht wissen kann, was Sie wollen. Du könntest immer auf die explizite Funktionserfassung überspringen und hast einfach einen Callable-Objekt-Parameter: 'template automatischer Aufruf (F f, T * t, Args && ... args) { zurück (t -> * f) (std :: vorwärts (args) ...); } ' – chris

Antwort

11

Die Art und Weise Sie Ihre Funktion Vorlage aufrufen, wird die Template-Parameter Pack Args aus zwei Quellen abgeleitet werden:

  • Der Typ des Zeigers an das Mitglied Funktion - int (Calculator::*)(const int&, const int&)
  • die tatsächlichen Typen der Argumente (*a, *b) Sie für den Funktionsparameter Paket übergeben - int &, int &

für den Abzug erfolgreich zu sein, das Ergebnis ableiten muss Exac tally match. Offensichtlich nicht.

Dies ist nicht neu oder speziell für Variadic Vorlagen. Sie haben das gleiche Problem, wenn Sie versuchen, std::max(1, 1.5) zu tun - der Compiler leitet int von einem Argument, double aus dem anderen, und Abzug scheitert, weil die beiden Konflikt.

Simplest fix wahrscheinlich zwei Packungen nimmt:

template <typename T, typename R, typename... Args1, typename... Args2> 
R call(R (T::*fn)(Args1...), T *t, Args2&&... args) { 
    return ((*t).*fn)(std::forward<Args2>(args)...);  
} 
+0

Natürlich :) Danke. – jeffreyveon

Verwandte Themen