C++ の typename キーワード
この記事では、C++ のキーワード typename
について説明します。
キーワード typename
の重要性を理解するには、修飾
および依存
名の重要な概念を理解する必要があります。
C++ での修飾名と非修飾名
修飾名はスコープを指定します。それをよりよく理解するために例を見てみましょう。
#include <bits/stdc++.h>
int main() { std::cout << "Hello world!" << std::endl; }
cout
および endl
への参照は、ここでは修飾名です。しかし、両方を using
宣言でスコープに入れると、つまり、using namespace std
で、それ自体で cout
を使用すると、std::
がないため、unqualified
名になります。
C++ での依存名と非依存名
依存名は、テンプレート
パラメーターに依存する名前です。
それをよりよく理解するためにサンプルコードを見てみましょう。
template <class T>
class MyClass {
int i;
vector<int> vi;
vector<int>::iterator vitr;
T t;
vector<T> vt;
vector<T>::iterator viter;
}
最初の 3つの宣言は、テンプレート宣言時にタイプがわかっているため、非依存名として知られています。
一方、2 番目の宣言は T
、vector<T>
および vector<T>::iterator
で、これらはテンプレートパラメーターの T
に依存しているため、インスタンス化の時点まで型がわからない依存した名前です。
C++ での typename
キーワードの使用
原則として、typename
キーワードは、タイプを参照する修飾名または従属名の前に使用する必要があります。
そのため、キーワード typename
が導入され、後続の識別子が静的メンバー変数ではなくタイプであることを指定します。
class A {
public:
typedef int myPtr;
};
template <class T>
class myClass {
public:
typename T::SubType* myPtr;
}
上記のコードで、typename
キーワードは、SubType
がクラス T
のタイプであることをコンパイラーに通知します。つまり、ポインターmyptr
は T::SubType
のタイプです。
typename
キーワードがない場合、SubType
は静的メンバーと見なされ、コンパイラーは、タイプ T
の SubType
とポインターmyptr
の乗算として評価します。
T::SubType * myptr //compiler will think it's multiplication
もし、上記のコードでキーワード typename
を使用しなかった場合、コンパイラは T::SubType
が型名なのか T
のスタティックメンバなのか分からないため、コンパイル時のエラーとなります。