Es gibt eine Technik, die ich manchmal beim Überschreiben von template
-Funktionen verwende, die folgendermaßen aussieht:
Dies unterscheidet do_stuff
von do_stuff
, weil einer 0 oder mehr UniqueEnum<1>
s und der andere 0 oder mehr UniqueEnum<-1>
s benötigt. gcc 4.8 betrachtet diese verschiedenen leeren Pakete als unterschiedlich.
In der neuesten Version von clang, die ich versucht habe, scheitert dies jedoch: Es behandelt die Funktion mit 0 UniqueEnum<1>
s als die gleiche Funktion wie die Funktion mit 0 UniqueEnum<-1>
s.
Es gibt einfache Problemumgehungen, die beim Claming funktionieren, aber ich frage mich, ob meine obige Technik legal ist - machen zwei Funktionen template
s, die sich nur durch leere variardic Parameter unterscheiden, tatsächlich anders?
Ich denke, GCC hat Recht, und Ihre Technik ist richtig. Da das Argument type für C
explizit angegeben wird, lautet die Frage im Wesentlichen:
a. Substitution von C
überall sonst in der Funktionsschablonen-Signatur passiert zuerst, und dann wird Typ-Deduktion durchgeführt (was zu einem Substitutionsfehler führen sollte); oder
b. type deduction wird zuerst durchgeführt, und dann wird die Ersetzung durchgeführt (was nicht zu einem Substitutionsfehler führen würde, weil das entsprechende Argument-Paket leer wäre und somit keine Substitution durchgeführt werden müsste).
Es scheint, dass GCC (1) annimmt, während Clang (2) annimmt. Paragraph 14.8.2 / 2 des C ++ 11 Standards spezifiziert:
Wenn eine explizite Vorlagenargumentliste angegeben wird, müssen die Vorlagenargumente mit der Datei kompatibel sein Template-Parameterliste und muss wie unten beschrieben zu einem gültigen Funktionstyp führen; Andernfalls geben Sie den Abzug ein schlägt fehl. Insbesondere werden die folgenden Schritte ausgeführt, wenn eine explizit angegebene Vorlage ausgewertet wird Argumentliste in Bezug auf eine gegebene Funktionsvorlage:
- Die angegebenen Vorlagenargumente müssen mit den Vorlagenparametern übereinstimmen (d. h. type, non-type, Vorlage). Es darf nicht mehr Argumente geben als Parameter, es sei denn, mindestens ein Parameter ist ein Template-Parameterpaket, und für jeden Nicht-Pack-Parameter muss ein Argument angegeben werden. Andernfalls, Typabzug schlägt fehl.
- Nicht-type Argumente müssen mit den Typen der entsprechenden Nicht-Typ-Template-Parameter übereinstimmen oder müssen auf die Typen der entsprechenden Nicht-Typparameter gemäß 14.3.2 umzustellen Typabzug schlägt fehl.
- Die angegebenen Vorlagenargumentwerte werden für die entsprechenden Vorlagenparameter als ersetzt unten angegeben .
Der folgende Absatz sagt dann:
Nachdem diese Ersetzung durchgeführt wurde, werden die in 8.3.5 beschriebenen Anpassungen der Funktionsparameter durchgeführt. [...]
Darüber hinaus bestimmt Absatz 14.8.2 / 5:
Der resultierende substituierte und angepasste Funktionstyp wird als der Typ der Funktionsvorlage für die Vorlage verwendet Argumentabzug . [...]
Schließlich gilt Absatz 14.8.2 / 6 wie folgt:
An bestimmten Punkten im Template Argument Deduction-Prozess ist es notwendig, einen Funktionstyp zu nehmen, der verwendet Vorlagenparameter und ersetzt diese Vorlagenparameter durch die entsprechende Vorlage Argumente. Dies wird am Anfang der Vorlagenargumentableitung bei einer explizit angegebenen Vorlage ausgeführt Argumente werden in den Funktionstyp und wieder am Ende der Vorlageargumentableitung eingesetzt wenn irgendwelche Template-Argumente, die abgeleitet oder von Standardargumenten erhalten wurden, ersetzt werden.
Dies alles scheint zu implizieren, dass die erste Ersetzung durchgeführt wird, und dann die Argumentableitung des Templates. Daher sollte in beiden Fällen ein Substitutionsfehler auftreten, und eine der beiden Vorlagen sollte aus der Überladungsgruppe verworfen werden.
Leider scheint es keine klare Spezifikation dafür zu geben, wie das Verhalten aussehen sollte, wenn Vorlagenargumente abgeleitet und nicht explizit angegeben werden.
Tags und Links c++ c++11 templates language-lawyer sfinae