2017-12-28 3 views
2

Ich versuche herauszufinden, ob das, was ich schrieb, ist legal C++ 14 w.r.t. Überschreibungsauflösung der eindeutigen Funktionsschablone.Funktion Vorlage Überladung Auflösung schlägt in Visual C++ 2017

Meiner Meinung nach sollte das folgende Programm kompilieren und 3 zurückgeben.

Verschiedene Versionen von Clang und GCC berechnen nur das zur Kompilierzeit (unter Verwendung -std=c++14 -O2), aber Visual C++ 2017 (Version 15.5.2; neueste Aktualisierung zum Zeitpunkt des Schreibens) Drosseln mit der folgenden Fehlermeldung.

enum class Enum0 { State }; 
enum class Enum1 { State }; 

template <Enum0 Param0 = Enum0::State> 
int get() 
{ 
    return 1; 
} 

template <Enum1 Param1> 
int get() 
{ 
    return 2; 
} 

int main() 
{ 
    int sum = 0; 
    sum += get(); // should call instantiation of first function template 
    sum += get<Enum1::State>(); // should call instantiation of second function template 
    return sum; 
} 

Dies ist die emittierte Fehlermeldung von der Visual C++ Compiler:

20 : <source>(20): error C2668: 'get': ambiguous call to overloaded function 
11 : <source>(11): note: could be 'int get<Enum1::State>(void)' 
5 : <source>(5): note: or  'int get<Enum0::State>(void)' 
20 : <source>(20): note: while trying to match the argument list '()' 

https://godbolt.org/g/PhH2VY für eine Live-Demonstration sehen (und https://godbolt.org/g/BVEv79 für das vorherige Codebeispiel vor, die Frage der Bearbeitung). Ändern Sie den Compiler in MVSC, damit die Kompilierung fehlschlägt. GCC und Clang geben kein Problem an. Beide schön strahlen die folgende x86 assembly:

 mov  eax, 3 
     ret 

Sind GCC und Clang zu nachsichtig, oder ist dies ein Problem mit Visual C++?

+0

Das klingt nach etwas zu fragen unter https://connect.microsoft.com/VisualStudio – SoronelHaetir

+0

Sicher. Sobald es halbwegs feststeht, dass dies tatsächlich legal C++ 14 ist und kompiliert werden soll, werde ich das trotzdem tun. – kmhofmann

+0

Ich bin mir ziemlich sicher, dass dein Problem nichts mit dem dritten Fall zu tun hat und die ersten beiden können reduziert werden. Warum bieten Sie keine [mcve] –

Antwort

0

Das ist eine gute Frage, nicht wahr? Wenn ich den zweiten Anruf wechseln mit zu bekommen:

sum += get<Enum1::State, int>(0.0); // should call instantiation of second function template 

... dann kompiliert es ...

Hinweis, füge ich ein zweites Template-Argument. In meiner täglichen Arbeit benutze ich einen alten C++ - Dialekt, der mit MFC kompatibel ist ... also nimm meine Überlegungen mit einem Körnchen Salz. Aber da Sie der Vorlage nur ein Argument zur Verfügung stellen und die zweite Vorlage zwei Argumente benötigt, ISTTM, dass der VC++ - Compiler versucht, die erste Vorlage zu verwenden, weil sie Standardargumente hat und nur ein Argument annehmen kann. Es wählt also diese Vorlage aus, kann aber die Konvertierung von Enum1 nach Enum0 nicht durchführen.

+0

Das mag sein, aber der ganze Sinn dieser Art von API (sowohl in meinem realen Code als auch in diesem Beispiel) ist es, * nicht * alle Template-Parameter eingeben zu müssen, sondern entweder das eine oder das andere verwenden zu können beide. Wiederum sind "Enum0" und "Enum1" unterschiedliche Typen, so dass es während der Argumentableitung/Überladungsauflösung keine Mehrdeutigkeit geben sollte. – kmhofmann

Verwandte Themen