次の例では、 のインスタンス化を引き起こすA
メンバ typedefがあります。Instantiate
B<A>
template<typename T>
struct B
{
typedef typename T::Before Before; // ok
typedef typename T::After After; // error: no type named 'After' in 'A<int>'
};
template<typename T>
struct A
{
typedef int Before;
typedef typename B<A>::After Instantiate;
typedef int After;
};
template struct A<int>; // instantiate A<int>
私が試したすべてのコンパイラは、表示されているA::Before
が表示されA::After
ていないと報告しています。この動作は標準に準拠していますか? もしそうなら、標準は のA
インスタンス化中にどの名前を表示する必要があるかをどこで指定していますB<A>
か?
従属名が「テンプレートのインスタンス化の時点で検索される」場合、これは ? などのテンプレート パラメータによって修飾された名前のシナリオで何を意味しますT::After
か?
編集: A がテンプレートでない場合、同じ動作が発生することに注意してください:
template<typename T>
struct B
{
typedef typename T::Before Before; // ok
typedef typename T::After After; // error: no type named 'After' in 'A'
};
struct A
{
typedef int Before;
typedef B<A>::After Instantiate;
typedef int After;
};
.. そして G++ は以下を受け入れますが、Clang は受け入れません:
template<typename T>
struct B
{
static const int value = 0;
static const int i = T::value; // clang error: not a constant expression
};
struct A
{
static const int value = B<A>::value;
};
編集: C++03 標準を読んだ後:
[temp.dep.type] テンプレート パラメーターの場合、型は依存します
したがってT
、依存しています。
[temp.res] テンプレート定義で使用される名前の宣言を検索する場合、通常の検索規則が非依存の名前に使用されます。テンプレート パラメータに依存する名前の検索は、実際のテンプレート引数が判明するまで延期されます。
したがって、 のルックアップはT::After
、 の引数が判明するまで延期さT
れます。
[temp.inst] クラス テンプレートの特殊化が明示的にインスタンス化されていない限り ... 完全に定義されたオブジェクト型を必要とするコンテキストで特殊化が参照されると、クラス テンプレートの特殊化は暗黙的にインスタンス化されます。
したがって、の宣言にA<int>::Instantiate
は、のインスタンス化が必要ですB<A>
(ネストされた名前指定子で使用されるため)。
A<int>::After
の宣言の時点では見えないA<int>::Instantiate
ため、コンパイラの動作は理にかなっていますが、この動作を明示的に説明している C++03 は見たことがありません。最も近いのは、このややあいまいな段落でした。
[temp.dep.res] 依存する名前の解決では、次のソースからの名前が考慮されます。
— テンプレートの定義時に表示される宣言。