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.

¿Por qué falla la compilación al inicializar un parámetro de plantilla no tipo con un marcador de posición para un tipo de clase deducido?

Considere el siguiente código:

struct Base_string { char data[1 << 5]; };

template<typename base="">
struct Derived: Base { };

Derived(char const*) -> Derived<base_string>;

template<derived>
struct S { };

S<{"Test"}> s; // Error

La última línea, en la cual se instancia S, no compila. Yo esperaba que funcionara, porque [temp.arg.nontype#1] establece que:

Si el tipo T de un template-parameter contiene […] un marcador de posición para un tipo de clase deducido, el tipo del parámetro es el tipo deducido para la variable x en la declaración inventada T x = template-argument;

En mi caso, esta declaración inventada se vería así: Derived x = {"Test"};, y en realidad, declarar una variable de esta forma en el programa no produce errores, el tipo se deduce correctamente.
También creo que el problema no está en la sintaxis de inicialización en agregado en sí – cambiar la definición del template S a:

template<base_string>
struct S { };

y instanciarlo de la misma manera (S<{"Test"}> s;) no produce errores.

Sé que podría simplemente especificar el tipo explícitamente, de esta forma: S<derived{"test"}> s;, pero no estoy buscando una solución alternativa, quiero entender por qué la deducción falla aquí.</derived{“test”}>

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    La deducción falla aquí debido a que la deducción de tipos de clase no está permitida en una deducción de argumento de plantilla para un parámetro de plantilla que no es de tipo. Mientras que [[temp.arg.nontype#1]] establece que el tipo del parámetro es el tipo deducido para la variable x en la declaración inventada T x = template-argument;, esto solo se aplica a la deducción del tipo de template-argument, no a la deducción del tipo de un parámetro de plantilla que no es de tipo.

    En el caso de S, el parámetro de plantilla es un parámetro de plantilla que no es de tipo de tipo Derived, y el argumento {"Test"} no es un tipo de clase deducido, sino más bien una expresión de inicialización de agregado que no se puede utilizar para deducir el tipo de Derived en un parámetro de plantilla que no es de tipo. Es por esto que la especificación explícita del tipo funciona (S<Derived{"Test"}> s;), ya que el tipo ya no se está deduciendo.

    Cambiar la definición de S para usar Base_string en lugar de Derived funciona porque en ese caso, el parámetro de plantilla es un parámetro de plantilla que no es de tipo de tipo Base_string, que se puede deducir a partir de la expresión de inicialización del agregado.

Comments are closed.