2010-05-14 19 views
8

Si tengo una plantilla de función con typename T, donde el compilador puede establecer el tipo por sí mismo, no tiene que escribir el tipo de forma explícita cuando llamo a la función como:Función de plantilla de llamada sin <>; inferencia de tipos

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> 

Pero si tengo una plantilla de función con dos typenames diferentes como:

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> 

¿es cierto que siempre tengo que especificar al menos 1 nombretipo? Supongo que la razón es porque C++ no puede distinguir funciones entre diferentes tipos de retorno.

Pero si uso una función nula y la entrega de una referencia, de nuevo, no tienen que especificar el nombre de tipo de retorno:

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> 

En caso de que la conclusión sea para evitar funciones con retorno y más prefieren void funciones que devuelven a través una referencia al escribir plantillas? ¿O existe la posibilidad de evitar escribir explícitamente el tipo de devolución? Algo así como "tipo de inferencia" para plantillas. ¿Es posible la "inferencia de tipo" en C++ 0x?

+0

Conversiones entre tipos hace que la idea de inferencia de tipos difícil de manejar, por lo que no se puede sobrecargar el tipo de retorno y debe especificar cuando se trata de un parámetro de plantilla. – Francesco

+0

Es posible que desee trabajar en su algoritmo de redondeo. ¿Qué debería sacar -1.54? Y: ¿y si quieres obtener un valor ** ** ** redondeado? – UncleBens

Respuesta

12

La resolución de sobrecarga se realiza solo en función de los argumentos de la función; el valor de retorno no se usa en absoluto. Si el tipo de devolución no puede determinarse según los argumentos, deberá especificarlo explícitamente.

No iría por el camino de "devolver" un valor a través de un parámetro de referencia; eso hace que el código de llamada no sea claro. Por ejemplo, yo prefiero esto:

double x = round<double>(y); 

sobre esto:

double x; 
round(x, y); 

porque en este último caso, es fácil confundir la entrada y la salida, y no es del todo claro que x es estar modificado.

En el caso particular de round, es probable que tenga sólo uno o dos tipos de TOut de todos modos, por lo que sólo puede dejar que el argumento de la plantilla a cabo:

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

encuentro roundToInt(x) un poco más claro que round<int>(x) porque es aclare para qué se utiliza el tipo int.

+1

En cuanto a la claridad: 'round_to (x)'? ;) – UncleBens

+0

Sí, eso sería bueno también. – Thomas

3

la conclusión de que para evitar funciones con el regreso y más prefieren funciones que devuelven vacíos a través de una referencia a la hora de escribir las plantillas

No, ¿por qué? ¿Qué ganas? Solo escriba inferencia (por lo tanto, menos código para escribir). Pero pierde la sintaxis mucho más lógica de asignar un valor (y en consecuencia más código para escribir). Así que una cosa ganó, otra perdió. No veo el beneficio en general.

Puede incluso ayudar para tener que especificar el tipo de plantilla explícitamente: considere el caso de lexical_cast. No especificar el tipo de plantilla de devolución sería confuso.

2

permítaseme añadir a lo que los otros han dicho diciendo que debe preferir C++ fundición durante la fundición de estilo C.

vret = (TOut)(vin + 0.5); 

frente

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

vaciado estático siempre fallará si intenta convertir tipos no relacionados. Esto puede ayudar con la depuración.

+0

Y también tendrá advertencias/errores de tiempo de compilación, mucho mejor que encontrarlo en tiempo de ejecución. –

+0

¿Cuáles deberían ser los tipos implicados, de modo que un 'static_cast' arroje un resultado diferente que un molde de estilo C en esta plantilla? (Sí, en una función de utilidad puede esforzarse por tener un buen estilo, pero no veo tanto beneficio en el código matemático puro que hace la conversión entre tipos de números, para garantizar una publicación, y tal vez no un comentario). – UncleBens

Cuestiones relacionadas