Risoluzione dei nomi per i nomi in locale dichiarati
Il nome stesso del modello può fare riferimento a con o senza argomenti di modello.Nel modello di classe, il nome stesso fa riferimento al modello.In una specializzazione del modello o delle specializzazioni parziali, il nome da solo si riferisce alla specializzazione o alla specializzazione parziali.Altre specializzazioni o le specializzazioni parziali del modello possono anche possibile farvi riferimento, con gli argomenti di template appropriati.
Esempio
Il codice seguente mostra che il nome Della classe modello viene interpretato in modo diverso in una specializzazione o delle specializzazioni parziali.
// 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>.
};
In caso di conflitto di nomi tra un parametro di modello e un altro oggetto, il parametro di template può o non può essere nascosto.Le regole seguenti consentono di determinare la precedenza.
Il parametro di template è nel punto in cui innanzitutto viene visualizzato fino alla fine della classe o di modello di funzione.Se il nome viene visualizzato ancora presente nell'elenco di argomenti di modello o nell'elenco di classi base, si riferisce allo stesso tipo.In C++ standard, nessun altro nome che è identico al parametro di modello può essere dichiarato nello stesso ambito.Un'estensione Microsoft consente il parametro di template da ridefinire nel modello.Nell'esempio seguente viene illustrato l'utilizzo del parametro di template nella specifica di base di un modello di classe.
// template_name_resolution4.cpp
// compile with: /EHsc
template <class T>
class Base1 {};
template <class T>
class Derived1 : Base1<T> {};
int main() {
// Derived1<int> d;
}
Nel definire le funzioni membro di un modello all'esterno di template di classe, un nome di parametro di modello diverso può essere utilizzato.Se la definizione della funzione membro del modello utilizza un nome diverso per il parametro di modello che la dichiarazione fa e il nome utilizzato nei conflitti della definizione con un altro membro di dichiarazione, il membro nella dichiarazione del template ha la precedenza.
// 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();
}
Nella definizione di una funzione o una funzione membro di un modello dallo spazio dei nomi nel quale il modello è stato dichiarato, argomento di template ha la precedenza sui nomi di altri membri dello spazio dei nomi.
// 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();
}
Nelle definizioni al di fuori della dichiarazione della classe template, se una classe modello dispone di una classe base non dipende da un argomento di modello e se la classe base o quella dei membri con lo stesso nome come argomento di modello, la classe base o il nome del membro nasconde argomento di template.
// 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;
}