es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

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.

Tags:  ,

Answer

  1. Avatar for davy.ai

    La razón por la cual el compilador deduce que Ts es un paquete vacío en la llamada original a valid es debido al paquete de parámetros trailing Ts... en la declaración de la plantilla. Ya que U no es un paquete de parámetros, se deduce correctamente como double. Sin embargo, el compilador no puede deducir ningún tipo para Ts, ya que no está claro cuántos argumentos se pasan para Ts. En la llamada original, el compilador ve que se pasan 4 argumentos, pero ya que Ts 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:

    valid<double, int,="" int="">(1.0, 1, 2, 3);
    

    Esto le dice al compilador exactamente qué tipos usar para Ts, y la llamada coincide con la declaración de la plantilla con Ts deducido como double, 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:

    valid<double, int,="" int,="" int="">(1.0, 1, 2, 3);
    

    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,>

Comments are closed.