Reglas de deducción de tipos de plantilla de función.
Tengo lo siguiente:
template<typename ...Ts, typename U, typename=void>
void valid(Ts..., U){}
int main() {
valid(1.0, 1, 2, 3);
}
clang se queja:
note: la función candidata [con Ts = <>, U = double, $2 = void] no es viable: requiere 1 argumento, pero se proporcionaron 4
void valid(Ts..., U){}
^
y gcc se queja:
<source>:2:6: note: deducción / sustitución de argumentos de plantilla fallida:
<source>:5:10: note: el candidato espera 1 argumento, se proporcionaron 4
5 | valid(1.0, 1, 2, 3);
| ~~~~~^~~~~~~~~~~~~~
Según cling, parece que el compilador deduce que Tn
es un paquete vacío (es decir, <>). ¿Por qué es eso? Pensé que dado el conjunto de argumentos (1.0, 1, 2, 3), U
se deduciría como int
y Tn...
sería double, int, int
. ¿Cuáles son las reglas aquí para la deducción de tipos?
Si cambio el llamador a:
valid<double, int, int>(1.0, 1, 2, 3);
Funciona. Sin embargo, si lo cambio a:
valid<double, int, int, int>(1.0, 1, 2, 3);
Falla:
<source>:2:6: note: deducción / sustitución de argumentos de plantilla fallida:
<source>:5:33: note: el candidato espera 5 argumentos, se proporcionaron 4
5 | valid<double, int, int, int>(1.0, 1, 2, 3);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~
¿Qué reglas se usan aquí para determinar qué tipos puedo especificar en la lista de parámetros de tipo?
Gracias.
davy.ai
La razón por la cual el compilador deduce que
Ts
es un paquete vacío en la llamada original avalid
es debido al paquete de parámetros trailingTs...
en la declaración de la plantilla. Ya queU
no es un paquete de parámetros, se deduce correctamente comodouble
. Sin embargo, el compilador no puede deducir ningún tipo paraTs
, ya que no está claro cuántos argumentos se pasan paraTs
. En la llamada original, el compilador ve que se pasan 4 argumentos, pero ya queTs
puede estar vacío, no se puede hacer coincidir la llamada de función con la declaración de la plantilla.Para solucionar esto, se puede especificar explícitamente los tipos para
Ts
en la lista de argumentos de plantilla, tal y como se hizo en el segundo ejemplo:Esto le dice al compilador exactamente qué tipos usar para
Ts
, y la llamada coincide con la declaración de la plantilla conTs
deducido comodouble, int, int
. Sin embargo, si se especifica un número incorrecto de tipos en la lista de argumentos de plantilla, como en el tercer ejemplo:entonces el compilador no podrá coincidir la llamada con la declaración de la plantilla, ya que el número de tipos especificados no coincide con el número de parámetros de plantilla no paquete en la declaración. La regla aquí es simplemente que hay que especificar el número correcto de tipos en la lista de argumentos de plantilla, coincidiendo exactamente con el número de parámetros de plantilla sin paquete en la declaración.</double,></double,>