El siguiente código se compila aunque nonexisting_func()
no existe. El código se compila porque es una función miembro de una clase con plantilla, pero la función en sí no se compila porque no se está utilizando en el programa, ¿correcto? Entonces, ¿podría tener algún error de sintaxis dentro de heapify_down
y todo el código aún debería compilarse?
#include <iostream>
#include <vector>
template<typename T>
class heap
{
public:
void heapify_down(std::vector<T> &vec)
{
nonexisting_func(vec);
}
};
int main( )
{
heap<int> my_heap;
return 0;
}
Si mi entendimiento anterior es correcto, ¿por qué no se compila el siguiente código?
#include <iostream>
#include <vector>
template<typename T>
class heap
{
public:
void heapify_down(std::vector<T> &vec)
{
a;
nonexisting_func(vec);
}
};
int main( )
{
heap<int> my_heap;
return 0;
}
Compilar este código me da el error error: use of undeclared identifier 'a'
. ¿Por qué está tratando de compilar la función heapify_down()
ahora?
2 respuestas
El código de plantilla básicamente tiene dos pases por los que pasa. La primera pasada solo mira el código y se asegura de que sea sintácticamente correcto y de que cualquier código no dependiente sea correcto. Por código no dependiente, me refiero al código que no depende de los parámetros de la plantilla.
Después de eso hay un segundo pase que ocurre después de que la plantilla se instancia en realidad. En ese momento, no hay más código dependiente, ya que todos los parámetros de la plantilla son conocidos y el compilador puede examinar el código como lo haría para cualquier código que no sea de plantilla.
En
void heapify_down(std::vector<T> &vec)
{
nonexisting_func(vec);
}
La llamada a nonexisting_func
depende de vec
debido a ADL y vec
depende de T
, por lo que su compilación se aplaza. Es sintácticamente correcto, por lo que no se realizarán más comprobaciones hasta que se instancia. Si cambiaste de principal a
int main( )
{
std::vector<int> foo;
heap<int> my_heap;
my_heap.heapify_down(foo);
return 0;
}
Para que heapify_down
se instancia realmente, entonces obtendría un error del compilador como
main.cpp:22:7: error: use of undeclared identifier 'nonexisting_func'
nonexisting_func(vec);
^
main.cpp:30:12: note: in instantiation of member function 'heap<int>::heapify_down' requested here
my_heap.heapify_down(foo);
^
1 error generated.
También recibirías un error al usar
void heapify_down(std::vector<T> &vec)
{
::nonexisting_func(vec);
}
Debido a que ahora ya no tenemos un nombre no calificado, ADL se ignora, lo que significa que ::nonexisting_func
ya no es un nombre dependiente.
Con
void heapify_down(std::vector<T> &vec)
{
a;
nonexisting_func(vec);
}
a
no depende de T
, por lo que el compilador intenta buscarlo. No puede encontrarlo, por lo que obtiene un error. Si en cambio hubieras hecho
void heapify_down(std::vector<T> &vec)
{
this->a;
nonexisting_func(vec);
}
De nuevo, no recibirá un error hasta que cree una instancia de la función ya que a
ahora depende de this
y this
depende de T
.
El punto clave aquí es que nonexisting_func(vec);
va a significar algo diferente dependiendo de lo que sea T
(ya que vec es un vector<T>
).
Entonces, en ese caso, el compilador no puede intentar resolver la llamada a nonexisting_func()
de inmediato, ya que elimina la función, y solo puede hacerlo cuando llegue el momento de crear una instancia de la plantilla (lo cual nunca hace).
En el caso de a
, dado que ese identificador no depende de nada, el compilador debe realizar la búsqueda de inmediato. Digo debería porque MSVC en particular tiende a retrasar la búsqueda hasta la creación de instancias, aunque no debería hacerlo en papel.
Nuevas preguntas
c++
C ++ es un lenguaje de programación de propósito general. Originalmente fue diseñado como una extensión de C, y tiene una sintaxis similar, pero ahora es un lenguaje completamente diferente. Use esta etiqueta para preguntas sobre el código (que se compilará) con un compilador de C ++. Utilice una etiqueta específica de la versión para preguntas relacionadas con una revisión estándar específica [C ++ 11], [C ++ 14], [C ++ 17] o [C ++ 20] etc.