Variadic Templates: Fehler, Mehrdeutiger Aufruf "foo<1> oder foo<1,>"
-
Hallo zusammen,
ich wollte mich langsam an die Variadic Temples rantasten und spiele etwas damit herum. Allerdings scheitere ich schon bei meinem ersten Versuch.
template<int FIRST=0> void foo(void) { std::cout << FIRST << std::endl; } template<int FIRST, int... REST> void foo() { foo<FIRST>(); foo<REST...>(); } int main() { foo<1,2,3,4>(); return 0; }Die Idee ist, dass die Zahlen aus der Template-Parameterliste einfach auf die Konsole geschrieben wird - ohne die Verwendung von Funktions-Parametern.
Fehlermeldungen die ich aus Visual Studio 2015 erhalte sind:
1>test.cpp(16): error C2668: "foo": Mehrdeutiger Aufruf einer überladenen Funktion 1> test.cpp(15): note: kann "void foo<1,>(void)" sein 1> test.cpp(10): note: oder "void foo<1>(void)" 1> test.cpp(16): note: bei Anpassung der Argumentliste "()" 1> test.cpp(23): note: Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void foo<1,2,3,4>(void)".Ich habe denke ich noch zusätzlich das Verständnisproblem mit foo<1,> und foo<1>. Ich kann schließlich kein Code fehlerfrei kompilieren, der so aussieht:
template<int NUM,> void foo() {}Ich nehme mal an, dass der Compiler richtig arbeitet. Wo liegt bzw. liegen dann meine Fehler?
Vielen Dank für Eure Hilfe.
Viele Grüße,
jb
-
jb schrieb:
Hallo zusammen,
ich wollte mich langsam an die Variadic Temples rantasten und spiele etwas damit herum. Allerdings scheitere ich schon bei meinem ersten Versuch.
template<int FIRST=0> void foo(void) { std::cout << FIRST << std::endl; } template<int FIRST, int... REST> void foo() { foo<FIRST>(); foo<REST...>(); } int main() { foo<1,2,3,4>(); return 0; }Die Idee ist, dass die Zahlen aus der Template-Parameterliste einfach auf die Konsole geschrieben wird - ohne die Verwendung von Funktions-Parametern.
Ich glaube, das wird so nicht funktionieren, weil template partial specialization für Funktionen nicht erlaubt ist. Also mach mal mit Parametern. Allerdings gibt es da trotzdem noch eine Möglichkeit:
#include <iostream> template<int First = 0, int... Tail> void f(){ if(!sizeof...(Tail) && !First) return; std::cout << First; f<Tail...>(); }Aber das ist nicht so toll, da z.B. f<0>() nichts ausgeben würde.
Ich habe denke ich noch zusätzlich das Verständnisproblem mit foo<1,> und foo<1>. Ich kann schließlich kein Code fehlerfrei kompilieren, der so aussieht:
template<int NUM,> void foo() {}Ich nehme mal an, dass der Compiler richtig arbeitet. Wo liegt bzw. liegen dann meine Fehler?
Vielen Dank für Eure Hilfe.
Viele Grüße,
jb
Warum sollte das auch funktionieren. Was willst du damit erreichen?
-
Ein variables Templateargument kann auch leer sein, also können beide Templates mit nur einem Argument instantiiert werden.
Beide Funktionstemplates haben ausserdem die gleichen Funktionsargumente, daher ist keins der Templates spezieller als das Andere.
Mithin ist foo<x> in jedem beliebigen Kontext mehrdeutig.Abhilfe am besten dadurch, das die verschiedenen Templates nicht mit der gleichen Anzahl von Templateargumenten umgehen können oder die Typen inkompatibel sind.
z.B.template<int FIRST=0> void foo(void) { std::cout << FIRST << std::endl; } template<int FIRST, int SECOND, int... REST> void foo() { foo<FIRST>(); foo<SECOND, REST...>(); }oder
template<nullptr_t = nulltptr> // ints können nicht in nullptr_t konvertiert werden... void foo(void) { } template<int FIRST, int... REST> void foo() { std::cout << FIRST << std::endl; foo<REST...>(); }oder... mit C++17
template<int... bar> void foo() { ( bar << std::endl << ... << std::cout ); }
-
654664 schrieb:
jb schrieb:
Ich habe denke ich noch zusätzlich das Verständnisproblem mit foo<1,> und foo<1>. Ich kann schließlich kein Code fehlerfrei kompilieren, der so aussieht:
template<int NUM,> void foo() {}Warum sollte das auch funktionieren. Was willst du damit erreichen?
Na ja der Compiler meldet dass er ein Mehrdeutiger Aufruf festgestellt hat.
Es gibt Möglichkeit a: foo<1,>
Und es gibt Möglichkeit b: foo<1>Mir ist unklar wie er auf foo<1,> kommt, wenn es nicht mal validem Code entspricht. (Hier vermute ich mal ein Denkfehler oder eine falsch Interpretation meiner seits.)
654664 schrieb:
Ich glaube, das wird so nicht funktionieren, weil template partial specialization für Funktionen nicht erlaubt ist. Also mach mal mit Parametern.
Ok, wenn das nicht erlaubt ist, dann ist klar warum es nicht geht. Vielen Dank dafür. Kennst Du auch noch den Grund warum es verboten ist?
EDIT:
Hab erst jetzt Deinen, Camper, Beitrag gelesen. Danke dafür.