C++ 移行ガイド

型名の解決

C++ 標準には、識別子が型名であるかどうかを判定するための新しい規則が導入されています。次の例で、それらの規則について説明します。


typedef int S;
class B { ... typedef int U; ... }
template< class T > class C : public B {
    S    s; // OK
    T    t; // OK
    U    x; // 1. C++標準では無効
    B::U y; // 2. C++標準では無効
    T::V z; // 3. C++標準では無効
};

新しい言語規則では、テンプレート中の型名を解決するために、基底クラス名が自動的に検索されることはないと規定されています。また、キーワードの typename で宣言されていないかぎり、基底クラスやテンプレートパラメータクラスからとられた名前が型名になることはないとも規定されています。

上記の例の最初の無効な行 (1.) では、修飾クラス名とキーワードを使用せずに B から U を型として継承しようとしています。2 行目の無効な行 (2.) では、型は基底クラスの名前によって正しく修飾されてはいますが、typename 修飾子がありません。3 行目の無効な行 (3.) では、テンプレートパラメータからとられた型 V が使用されますが、キーワードの typename が省略されています。この型が基底クラスやテンプレートパラメータのメンバーに依存することはないため、s の定義は有効です。同様に、t の定義では、型の T (型である必要があるテンプレートパラメータ) がそのまま使用されるため、有効になります。

正しい実装は次のとおりです。


typedef int S; 
class B { ... typedef int U; ... } 
template< class T > class C : public B {
    S             s; // OK
    T             t; // OK
    typename B::U x; // OK
    typename B::U y; // OK
    typename T::V z; // OK
};