2012-04-05 7 views
12

Wenn Sie eine Funktion überlasten und sie dann mit einem Argument nennen, die sich perfekt einer der Überlastungen SpieleRegeln für die implizite Konvertierung von Template-Argumente

int f(int){return 3;} 
int f(bool){return 4;} 
...  //inside main() 
f(1);  //Calls f(int) 

der Compiler einfach wählt diese (perfekt) Spiel, bevor Sie implizite Konvertierungen versuchen . Allerdings habe ich versucht, eine Funktion TEMPLATE zu überlasten, wie in

template <bool veracity> 
int f(){return 1;} 

template <int amount> 
int f(){return 2;} 

...  //inside main() 
f<1>(); 

aber der Compiler auf den überlasteten f() complainning über mehrdeutigen Anruf hält, die besagt, es könnte entweder f<true>() oder f<1>() sein. Sollte der Compiler nicht einfach die perfekte Übereinstimmung wählen, anstatt zu versuchen, in wahr zu konvertieren?

Ich hatte den Eindruck, dass die implizite Konvertierung für Template-Argumente tatsächlich restriktiver war als die implizite Konvertierung von Funktionsargumenten. Gibt es eine Möglichkeit, dieses Problem zu umgehen?

Antwort

8

Das Argument, das Sie liefern, ist kein Typ, es ist ein Wert, also sind die Regeln ein bisschen anders - Sie müssen die Regeln für Nicht-Typ-Argumente anwenden. Für Nicht-Typ-Argumente sind implizite Konvertierungen zulässig. §14.3.2/5:

Die folgenden Konvertierungen werden für jeden Ausdruck ausgeführt, der als nicht typisiertes Template-Argument verwendet wird. Wenn ein nicht-types Template-Argument nicht in den Typ des entsprechenden Template-Parameters konvertiert werden kann, ist das Programm schlecht formatiert.

- Für einen nicht typisierten Template-Parameter vom Integral- oder Enumerationstyp werden Konvertierungen angewendet, die in einem konvertierten konstanten Ausdruck (5.19) erlaubt sind.

In C++ 03 ist die Formulierung leicht unterschiedlich, aber die Wirkung im wesentlichen identisch (auch §14.3.2/5):

- für einen Nicht-Typ-Template Parameter des Integrals oder Aufzählungstyp, integrale Promotionen (4.5) und integrale Konvertierungen (4.7) werden angewendet.

So oder so, da 1 ist sowohl ein int und implizit umwandelbar in ein bool, Ihr Anruf nicht eindeutig ist.

+0

ich sehe. Weißt du, ob es einen bestimmten Grund gibt, warum die Regeln so sind? Ich meine, gibt es einige technische Schwierigkeiten oder etwas, was es für Compiler praktisch unmöglich machen würde, die "exact-match-first/implicit-conversion-second" -Logik (die in Funktionsargumenten verwendet wird) auf Template-Argumente anzuwenden? – Malabarba

+0

Nein, ich weiß es nicht genau. Meine Vermutung ist, dass es vor allem daran liegt, dass die Regeln bereits komplex sind und dass das Hinzufügen von Regeln für das "Ranking", wie es beim Überladen der Fall ist, sie sogar noch stärker machen würde. Ich bin mir nicht sicher, aber aufgrund der Interaktion mit den anderen Regeln für Templates würde sich die Rangordnung zumindest ein wenig von der für Überladungen unterscheiden, also wäre das nicht nur eine Frage der Aussage "Die Kandidatenfunktionen bilden eine Überladungsgruppe, die gemäß §13.3 gelöst werden soll." –

+0

Sinn macht.Vielen Dank. =) – Malabarba

5

Da dies kein Compiler-Bug ist, sondern eine Sprachfunktion (siehe this answer), müssen Sie eine Arbeit finden.

Entweder müssen Sie Ihre Funktionen umbenennen oder können Sie diesen Hack verwenden:

template <typename T> struct F; 

template<> struct F<bool> { 
    template <bool veracity> 
    static int f(){return 1;} 
}; 

template<> struct F<int> { 
    template <int amount> 
    static int f(){return 2;} 
}; 

template <typename T, T value> 
int f() { return F<T>::template f<value>(); } 

// inside main(): 
std::cout << f<int, 2>() << '\n'; // prints 2 
std::cout << f<bool, 2>() << '\n'; // prints 1 
Verwandte Themen