言語弁護士のための別のもの。
次のコードでは、 の明示的なインスタンス化A<int>
が存在するかどうかに関係なく:
clang 3.0 では、 andの宣言が必要typename
ですが、 の宣言は必要ありません。Type1
Type3
Type2
gcc 4.8.1 ではtypename
の宣言が必要ですが、またはの宣言は必要ありType1
ません。Type2
Type3
struct C
{
int f1();
static int f2();
int m;
};
template<int i>
struct S
{
typedef int Type;
};
template<typename T>
struct B : C
{
};
template<typename T>
struct A : B<T>
{
void f()
{
typedef typename S<sizeof(C::f1())>::Type Type1; // typename required
typedef S<sizeof(C::f2())>::Type Type2; // typename not required
typedef typename S<sizeof(C::m)>::Type Type3; // typename not required?
}
};
template struct A<int>;
非静的メンバーへの呼び出しの暗黙のオブジェクト引数は であり、その型は依存しているため、typename
の宣言には図が必要です。[over.call.func] を参照してください。Type1
(*this)
修飾されていない関数呼び出しでは、名前は
->
or.
演算子によって修飾されず、primary-expression のより一般的な形式になります。名前は、関数呼び出しでの名前検索の通常の規則に従って、関数呼び出しのコンテキストで検索されます。そのルックアップによって見つかった関数宣言は、候補関数のセットを構成します。名前検索の規則により、候補関数のセットは、(1) 完全に非メンバー関数で構成されているか、(2) 完全に一部のクラス T のメンバー関数で構成されています。(1) の場合、引数リストは、呼び出しの式リスト。(2) の場合、引数リストは、修飾された関数呼び出しのように暗黙のオブジェクト引数の追加によって拡張された呼び出しの式リストです。キーワードthis
がスコープ内にあり、クラスを参照している場合T
、または の派生クラスのT
場合、暗黙のオブジェクト引数は(*this)
です。
このロジックに従うと、メンバーは静的であるため、typename
の宣言では必要ありません。式は非静的メンバーへの呼び出しではないため、の宣言にも必要Type2
ありません。typename
Type3
私はこれを読んだ:「テンプレート」と「タイプ名」のキーワードをどこに、なぜ入れなければならないのですか? .. [temp.dep.type] と [temp.dep.expr] のルールによって。式が依存しているかどうかを判断するときに、非静的メンバー関数名に特別な処理を施す必要があるかどうかを指定するものは何も見当たりません。規格はこれを指定していますか?
編集: [class.mfct.non-static] に基づくクラス メンバー アクセス式への変換に関する議論を削除しました - Casey の回答では、これについてより詳細に説明しています。