ローカルに宣言された名前の名前解決
テンプレートの名前自体はテンプレート引数なしで参照できます。クラス テンプレートのスコープ内で名前自体はテンプレートを示します。テンプレートの特化型または部分の特化型のスコープ内で単独で名前は特化したクラスまたは部分の特殊化を示します。テンプレートの特化したクラスまたは部分の特殊化では適切なテンプレート引数とで参照できます。
使用例
次のコードではクラス テンプレートの名前は特化したクラスまたは部分の特化型のスコープ内で期待どおりに解釈されることを示します。
// 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();
}
テンプレート クラスのテンプレート引数に依存しない基本クラスまたはメンバーの 1 つがテンプレート引数と同じ名前の場合基本クラスがある場合テンプレート クラスの宣言の外側にあるシグネチャで基本クラスまたはメンバー名はテンプレート引数を非表示にします。
// 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;
}