12

Ich möchte eine variadic Template-Funktion innerhalb einer Klasse haben. Die Variant-Template-Argumente sind Zeichen, die in einer Schleifen-ähnlichen Weise verarbeitet werden sollten. Also dachte ich daran, es wie in Haskell zu schreiben, mit Kopf/Schwanz die Liste aufzuteilen, bis ein Basisfall (leere Liste) erreicht ist.Variadic Template-Funktion: spezialisieren Kopf/Schwanz und leeren Basis-Fall

Als Beispiel, zählen wir nur die Anzahl der angegebenen Argumente (nur ein minimales Beispiel).

kam ich mit dem folgenden Code auf:

struct MyClass { 
    template<char ...X> 
    static int count(); 
}; 


template<> 
int MyClass::count<>() { 
    return 0; 
} 
template<char Head, char ...Tail> 
int MyClass::count<Head, Tail...>() { 
    return 1 + count<Tail...>(); 
} 

Doch diese doesn't seem to work:

prog.cpp:12:35: error: function template partial specialization ‘count<Head, Tail ...>’ is not allowed 
prog.cpp:12:5: error: prototype for ‘int MyClass::count()’ does not match any in class ‘MyClass’ 
prog.cpp:3:16: error: candidate is: template<char ...X> static int MyClass::count() 

Wie kann ich das erreichen? Ich weiß, dass eine Teilspezialisierung für Funktionen nicht unterstützt wird. Aber ich dachte, dass Spezialisierung eine variadic Vorlage in Kopf/Schwanz und leere Base-Case-Version ist kein Teil Spezialisierung, sondern eine volle Spezialisierung, aber vielleicht liege ich falsch? Muss ich dies als eine Klasse anstelle einer Funktion schreiben?

Ich habe Beispiele (printf) gefunden, die einen Basisfall implementieren, ohne die Template-Syntax zu verwenden. Aber ich denke, dass mein Fall ist anders, da der Aufruf für printf nicht Vorlagensyntax verwendet, sondern Typ Abzug, also printf(tail...) Anrufe printf(), wenn tail leer ist. Auf der anderen Seite ist in meinem Fall count<>() beim Aufrufen des Basisfalls nicht dasselbe wie count().

+0

Für den erwähnten Fall, Sie könnten nur ein Tupel aus dem var arg erstellen, und die Verwendung tuplesize. Vielleicht ist es einfacher mit Tupeln zu arbeiten, mit allem, was Sie sonst noch vorhaben? – Skeen

+0

@Skeen Dies war nur ein sehr minimalistisches Beispiel, bei dem das grundlegende Problem leicht diskutiert werden kann. Natürlich brauche ich etwas Komplexeres. AFAIK, Tupel funktioniert nur mit Typen, nicht mit Werten. – leemes

+1

Tupel können auch Daten speichern und sie scheinen viel einfacher zu arbeiten, wenn Sie mich fragen. – Skeen

Antwort

17

Ich würde sagen, es ist in der Regel eine bessere Idee Vorlagen Funktion eher zu überlasten, als sie spezialisiert:

struct MyClass { 
    template<typename... Tail> 
    static int count() { 
     return 0; 
    } 

    template<char Head, char... Tail> 
    static int count() { 
     return 1 + count<Tail...>(); 
    } 
}; 

#include <iostream> 

int main() { 
    std::cout << MyClass::count<'f','o','o'>(); 
} 

Und hier ist ein live example. Ich würde auch erwähnen, dass der eingebaute Operator sizeof... könnte für diesen Zweck verwendet werden:

struct MyClass { 
    template<char... Chars> 
    static int count() { 
     return sizeof...(Chars); 
    //   ^^^^^^^^^ 
    } 
}; 
+0

Oh mein Gott, total überladen vergessen. Vielen Dank! (off topic: LWS> ideone?) – leemes

+0

@leemes: Gern geschehen, hoffe es hilft! –

+0

Natürlich gibt es eine Größe von, die 'count' war nur das einfachste Beispiel, das ich mir vorstellen konnte, das immer noch das grundlegende Problem zeigt. – leemes