La resolución de nombres para Locally declarado nombres
El mismo nombre de plantilla se puede hacer referencia con o sin los argumentos.En el ámbito de una plantilla de clase, el nombre propio hace referencia a la plantilla.En el ámbito de una especialización de plantilla o de especialización parcial, el nombre sólo hace referencia a la especialización o la especialización parcial.Otras especializaciones o especializaciones parciales de plantillas se pueden hacer referencia, con los argumentos correspondientes de la plantilla.
Ejemplo
El código siguiente muestra el nombre de una plantilla de clase se interpreta de manera diferente en el ámbito de una especialización o de especialización parcial.
// template_name_resolution3.cpp
// compile with: /c
template <class T> class A {
A* a1; // A refers to A<T>
A<int>* a2; // A<int> refers to a specialization of A.
A<T*>* a3; // A<T*> refers to the partial specialization A<T*>.
};
template <class T> class A<T*> {
A* a4; // A refers to A<T*>.
};
template<> class A<int> {
A* a5; // A refers to A<int>.
};
En el caso de un conflicto de nombres entre un parámetro de plantilla y otro objeto, el parámetro de plantilla puede o no puede ocultar.Las reglas siguientes ayudarán a determinar la prioridad.
El parámetro de plantilla está en ámbito de punto donde primero aparece hasta el final de la plantilla de clase o de la función.Si el nombre aparece de nuevo en la lista de argumentos de plantilla o en la lista de clases base, hace referencia al mismo tipo.En C++ estándar, ningún otro nombre que es idéntico al parámetro de plantilla se puede declarar en el mismo ámbito.Una extensión de Microsoft permite que el parámetro de plantilla es volver a definir en el ámbito de la plantilla.El ejemplo siguiente muestra cómo usar el parámetro de plantilla en la especificación base de una plantilla de clase.
// template_name_resolution4.cpp
// compile with: /EHsc
template <class T>
class Base1 {};
template <class T>
class Derived1 : Base1<T> {};
int main() {
// Derived1<int> d;
}
Al definir las funciones miembro de una plantilla fuera de la plantilla de clase diferente, un nombre de parámetro de plantilla puede utilizar.Si la definición de función miembro desde la plantilla utiliza un nombre diferente para el parámetro de plantilla que hace la declaración, y el nombre utilizado en los conflictos de definición con otro miembro de declaración, el miembro en la declaración de plantilla tiene prioridad.
// template_name_resolution5.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
template <class T> class C {
public:
struct Z {
Z() { cout << "Z::Z()" << endl; }
};
void f();
};
template <class Z>
void C<Z>::f() {
// Z refers to the struct Z, not to the template arg;
// Therefore, the constructor for struct Z will be called.
Z z;
}
int main() {
C<int> c;
c.f();
}
Al definir una función de plantilla o la función miembro fuera del espacio de nombres en el que la plantilla se declaró, el argumento de plantilla tiene prioridad sobre los nombres de otros miembros del espacio de nombres.
// template_name_resolution6.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
namespace NS {
void g() { cout << "NS::g" << endl; }
template <class T> struct C {
void f();
void g() { cout << "C<T>::g" << endl; }
};
};
template <class T>
void NS::C<T>::f() {
g(); // C<T>::g, not NS::g
};
int main() {
NS::C<int> c;
c.f();
}
En las definiciones que están fuera de la declaración de clase de plantilla, si una clase de plantilla tiene una clase base que no depende de un argumento de plantilla y si la clase base o uno de sus miembros tiene el mismo nombre que un argumento de plantilla, la clase base o el nombre de miembro oculta el argumento de plantilla.
// template_name_resolution7.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
struct B {
int i;
void print() { cout << "Base" << endl; }
};
template <class T, int i> struct C : public B {
void f();
};
template <class B, int i>
void C<B, i>::f() {
B b; // Base class b, not template argument.
b.print();
i = 1; // Set base class's i to 1.
}
int main() {
C<int, 1> c;
c.f();
cout << c.i << endl;
}