2010-05-14 9 views
8

Wenn ich eine Funktion Vorlage mit typename T haben, wo der Compiler den Typ von selbst einstellen kann, muss ich den Typ nicht explizit schreiben, wenn ich die Funktion wie nennen:Aufruf der Vorlagenfunktion ohne <>; Typinferenz

template < typename T > 
T min(T v1, T v2) { 
    return (v1 < v2) ? v1: v2; 
} 
int i1 = 1, i2 = 2; int i3 = min(i1, i2); //no explicit <type> 

Aber wenn ich eine Funktionsschablone mit zwei verschiedenen typenames wie:

template < typename TOut, typename TIn > 
TOut round(TIn v) { 
    return (TOut)(v + 0.5); 
} 
double d = 1.54; 
int i = round<int>(d); //explicit <int> 

Ist es wahr, dass ich mindestens 1 Typnamen immer angeben muß? Ich nehme an, der Grund ist, weil C++ Funktionen zwischen verschiedenen Rückgabetypen nicht unterscheiden kann.

Aber wenn ich eine Lücke Funktion und Übergabe eine Referenz verwenden, wieder muß ich nicht explizit die Rückkehr Typname angeben:

template < typename TOut, typename TIn > 
void round(TOut & vret, TIn vin) { 
    vret = (TOut)(vin + 0.5); 
} 
    double d = 1.54; 
    int i; round(i, d); //no explicit <int> 

Sollte die Abschluss-Funktionen zu vermeiden, mit Rückgabe- und mehr bevorzugt void Funktionen, die über das Rück eine Referenz beim Schreiben von Vorlagen? Oder gibt es eine Möglichkeit zu vermeiden, den Rückgabetyp explizit zu schreiben? Etwas wie "Inferenz eingeben" für Vorlagen. Ist "Typ-Inferenz" in C++ 0x möglich?

+0

Durch die Umwandlung zwischen Typen wird die Typinferenz-Idee unübersichtlich, sodass Sie die Rückgabetypen nicht überladen können und sie angeben müssen, wenn es sich um einen Vorlagenparameter handelt. – Francesco

+0

Sie möchten vielleicht an Ihrem Rundungsalgorithmus arbeiten. Was sollte -1.54 als herauskommen? Und: Was ist, wenn Sie einen abgerundeten ** doppelten ** Wert erhalten möchten? – UncleBens

Antwort

12

Die Überladungsauflösung erfolgt nur basierend auf Funktionsargumenten; Der Rückgabewert wird überhaupt nicht verwendet. Wenn der Rückgabetyp anhand der Argumente nicht ermittelt werden kann, müssen Sie ihn explizit angeben.

Ich würde nicht den Weg gehen "zurück" einen Wert durch einen Referenzparameter; das macht den Anrufcode unklar. Zum Beispiel würde ich das vorziehen:

double x = round<double>(y); 

über diese:

double x; 
round(x, y); 

weil im letzteren Fall ist es einfach, Eingang und Ausgang zu verwirren, und es ist nicht klar, dass x zu sein, ist geändert.

Im speziellen Fall von round, müssen Sie wahrscheinlich nur ein oder zwei Arten für TOut sowieso, so dass Sie nur die Vorlage Argument auslassen könnten:

template<typename TIn> 
int roundToInt(TIn v) { 
    return (int)(v + 0.5); 
} 

ich roundToInt(x) ein wenig klarer als round<int>(x) finden, weil es Stellen Sie fest, wofür der Typ int verwendet wird.

+1

In Bezug auf Klarheit: 'round_to (x)'? ;) – UncleBens

+0

Ja, das wäre auch nett. – Thomas

3

die Schlussfolgerung Funktionen mit Rückkehr zu vermeiden und mehr Leere Funktionen bevorzugen, die über einen Verweis zurück, wenn Vorlagen

Kein Schreiben, warum? Was gewinnst du? Geben Sie nur Inferenz ein (also weniger Code zum Schreiben). Aber Sie verlieren die viel logischere Syntax der Zuweisung eines Wertes (und folglich mehr Code zum Schreiben). Also eine Sache gewonnen, eine andere verloren. Ich sehe den Nutzen im Allgemeinen nicht.

Es kann sogar Hilfe haben den Vorlagentyp explizit angeben: den Fall lexical_cast betrachten. Wenn Sie den Typ der Rückgabemaske nicht angeben, ist das verwirrend.

2

Lassen Sie mich hinzufügen, was die anderen gesagt haben, indem Sie sagen, dass Sie C++ Casting C-Style Casting bevorzugen sollten.

vret = (TOut)(vin + 0.5); 

gegen

vret = static_cast<TOut>(vin + 0.5); 

statischen Guss wird immer fehlschlagen, wenn Sie versuchen, nicht verwandte Arten zu konvertieren. Dies kann beim Debuggen helfen.

+0

Und Sie haben auch Kompilierungszeit Warnungen/Fehler, viel besser als zur Laufzeit herauszufinden. –

+0

Was müssten die beteiligten Typen sein, damit ein 'static_cast' ein anderes Ergebnis liefert als ein C-Style-Cast in diesem Template? (Ja, in einer Nutzenfunktion magst du nach einem guten Stil streben, aber ich sehe keinen so großen Vorteil im reinen mathematischen Code, der eine Umwandlung zwischen Zahlentypen vornimmt - um einen Beitrag zu rechtfertigen, und vielleicht nicht einen Kommentar.) – UncleBens

Verwandte Themen