2010-05-14 14 views
8

Se ho una funzione di modello con typename T, in cui il compilatore può impostare il tipo di per sé, non ho scrivere il tipo in modo esplicito quando chiamo la funzione come:Chiamata alla funzione modello senza <>; inferenza di tipo

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> 

Ma se devo un modello di funzione con due nomi dei tipi differenti come:

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> 

E 'vero che devo sempre specificare almeno 1 typename? Presumo che il motivo sia dovuto al fatto che C++ non è in grado di distinguere le funzioni tra diversi tipi di ritorno.

Ma se io uso una funzione vuoto e consegna un riferimento, ancora una volta non devo specificare esplicitamente il typename ritorno:

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> 

Qualora la conclusione essere quello di evitare funzioni con ritorno e più preferiscono void funzioni che restituiscono via un riferimento quando si scrivono i modelli? O c'è la possibilità di evitare di scrivere esplicitamente il tipo di reso? Qualcosa come "tipo di inferenza" per i modelli. "Inferenza del tipo" è possibile in C++ 0x?

+0

Il casting tra tipi rende l'idea di inferenza del tipo poco pratica, quindi non è possibile eseguire un overload sui tipi restituiti e deve specificarlo quando si tratta di un parametro del modello. – Francesco

+0

Si potrebbe voler lavorare sul proprio algoritmo di arrotondamento. Cosa dovrebbe uscire -1.54 come? E: cosa succede se si desidera ottenere un valore ** doppio ** arrotondato? – UncleBens

risposta

12

La risoluzione del sovraccarico viene eseguita solo in base agli argomenti della funzione; il valore di ritorno non viene utilizzato affatto. Se il tipo di reso non può essere determinato in base agli argomenti, dovrai specificarlo esplicitamente.

Non vorrei scendere il percorso di "restituzione" di un valore attraverso un parametro di riferimento; ciò rende poco chiaro il codice chiamante. Per esempio, io preferisco questo:

double x = round<double>(y); 

su questo:

double x; 
round(x, y); 

perché in quest'ultimo caso, è facile confondere ingresso e di uscita, e non è affatto chiaro se x è essere modificata.

Nel caso particolare di round, probabilmente avete bisogno di solo uno o due tipi per TOut comunque, quindi si può solo lasciare che l'argomento template out:

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

trovo roundToInt(x) un po 'più chiara di round<int>(x) perché è cancellare per cosa viene utilizzato il tipo int.

+1

Per quanto riguarda la chiarezza: 'round_to (x)'? ;) – UncleBens

+0

Sì, sarebbe bello anche questo. – Thomas

3

la conclusione essere quello di evitare le funzioni con ritorno e più preferiscono funzioni vuoto che restituiscono attraverso un riferimento durante la scrittura dei modelli

No, perché? Cosa ottieni? Digitare solo l'inferenza (quindi meno codice da scrivere). Ma tu perdi la sintassi molto più logica dell'assegnazione di un valore (e di conseguenza più codice da scrivere). Quindi una cosa è guadagnata, un'altra persa. Non vedo il beneficio in generale.

Potrebbe anche aiutare a specificare esplicitamente il tipo di modello: considerare il caso di lexical_cast. Non specificare il tipo di modello di reso sarebbe confuso.

2

Lasciatemi aggiungere ciò che gli altri hanno detto dicendo che dovresti preferire il cast di C++ rispetto al casting in stile C.

vret = (TOut)(vin + 0.5); 

contro

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

getto statico sarà sempre esito negativo se si tenta di convertire i tipi non correlati. Questo può aiutare con il debug.

+0

E avrai anche avvisi/errori di compilazione del tempo, molto meglio che scoprirlo in fase di runtime. –

+0

Quali sarebbero i tipi in questione, in modo che un 'static_cast' darebbe un risultato diverso rispetto a un cast in stile C in questo modello? (Sì, in una funzione di utilità si potrebbe cercare un buon stile, ma non vedo molti benefici nel puro codice matematico fare la conversione tra i tipi di numeri - per garantire un post, e non forse un commento.) – UncleBens

Problemi correlati