局部声明的名称转换
模板的名称可以是指有或没有模板参数。 在类模板的范围内,该名称引用模板。 在模板专用化还是部分专用化的范围内,将该名称引用专用化还是部分专用化。 其他专用化或模板的部分专用化也可以引用,用适当的模板参数。
示例
以下代码表示在专用化还是部分专用化的范围内,因此,类模板的名称的不同方式进行解释。
// 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++,与模板参数相同的其他名称在同一范围不能声明。 在模板的范围内, Microsoft 扩展允许模板参数重新定义。 下面的示例演示使用模板参数在类模板的基本规范。
// 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;
}