Разрешение имен для локально, объявленных имен
Имя самого шаблона можно обратиться к с или без аргументов шаблона.В области шаблонов класса, имя самого относится к шаблону.В области специализации шаблона или специализации частично попадания, имя единственный относится к специализации или специализации частично нажатия.Другие специализации или частично попадания специализации шаблона, также могут ссылаться с соответствующими аргументами шаблона.
Пример
Следующий код показывает, что имя a шаблона класса интерпретируется по-разному в область специализации или специализации частично нажатия.
// 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>.
};
В случае конфликта имен между параметром шаблона и другим объектом, параметр шаблона может быть или не быть скрыт.Следующие правила помогут определить приоритет.
Параметр шаблона в области из точки, где сначала он не будет появляться до конца шаблона класса или функции.Если имя появится в списке аргументов шаблона или в списке базовых классов, оно ссылается на тот же тип.В стандартном C++, никакое другое имя, идентично параметру шаблона можно объявить в той же области.Расширения Майкрософт позволяет параметр шаблона, который необходимо переопределить в области шаблонов.В следующем примере показано использование параметра шаблона в базовой спецификации шаблона класса.
// template_name_resolution4.cpp
// compile with: /EHsc
template <class T>
class Base1 {};
template <class T>
class Derived1 : Base1<T> {};
int main() {
// Derived1<int> d;
}
Определения функций-членов шаблона вне шаблона класса, другое имя параметра шаблона можно использовать.Если определение функции-члена шаблона использует другое имя для параметра, то объявление шаблона не произойдет, и имя, используемое в конфликтах определения с другим членом объявления члена в объявлении шаблона имеет приоритет.
// 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();
}
Указав функцию или функции-члена шаблона вне пространства имен, в котором шаблон был объявлен, аргумент шаблона имеет приоритет над именами других членов пространства имен.
// 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();
}
В определениях вне объявления класса шаблона, если класс шаблона имеет базовый класс, который не зависит от аргумента шаблона и если базовый класс или один из его элементов с одинаковыми именами в качестве аргумента шаблона, то базовый класс или имя скрывают аргумент шаблона.
// 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;
}