10

SFINAEに関するウィキペディアの記事を読んでいて、次のコード サンプルに遭遇しました。

struct Test 
{
    typedef int Type;
};

template < typename T > 
void f( typename T::Type ) {} // definition #1

template < typename T > 
void f( T ) {}                // definition #2

void foo()
{
    f< Test > ( 10 ); //call #1 

    f< int > ( 10 );  //call #2 without error thanks to SFINAE
}

今、私は実際に以前にこのようなコードを書いたことがあり、どういうわけか直観的に、単に「T」ではなく「typename T」と入力する必要があることを知っていました。ただし、その背後にある実際のロジックを知っておくとよいでしょう。説明したい人はいますか?

4

3 に答える 3

14

typename X::YX がテンプレート パラメーターであるか、テンプレート パラメーターに依存している場合は常に実行する必要がある短いバージョン。X が判明するまで、コンパイラは Y が型なのか値なのかを判断できません。したがってtypename、それがタイプであることを指定するために追加する必要があります。

例えば:

template <typename T>
struct Foo {
  typename T::some_type x; // T is a template parameter. `some_type` may or may not exist depending on what type T is.
};

template <typename T>
struct Foo {
  typename some_template<T>::some_type x; // `some_template` may or may not have a `some_type` member, depending on which specialization is used when it is instantiated for type `T`
};

コメントで sbi が指摘しているように、あいまいさの原因はY、静的メンバー、列挙型、または関数である可能性があることです。の型がわからXないとわかりません。typename標準では、キーワードを使用して明示的に型のラベルが付けられていない限り、コンパイラはそれが値であると想定する必要があると指定しています。

そして、コメンテーターは、別の関連するケースについても言及することを本当に望んでいるようです: ;)

従属名が関数メンバー テンプレートであり、明示的なテンプレート引数 ( など) を使用して呼び出す場合は、関数名の前にキーワードfoo.bar<int>()を追加する必要があります。templatefoo.template bar<int>()

これは、テンプレート キーワードがない場合、コンパイラはそれが値であると想定し、それbarに対してより小さい演算子 ( operator<) を呼び出したいためです。

于 2009-08-08T00:15:48.020 に答える
10

一般に、(C から継承された) C++ の構文には技術的な欠陥があります: パーサーは何かが型に名前を付けているかどうかを認識しなければなりませんX * Y。 Y から型 X のオブジェクトへ? すべては、X が型を指定するかどうかに依存します...!-)。「typename形容詞」を使用すると、必要に応じてそれを完全に明確かつ明示的にすることができます(これは、別の回答が言及しているように、テンプレートパラメーターが関与する場合に典型的です;-)。

于 2009-08-08T00:18:58.723 に答える
3

基本的に、typenameテンプレート コードを記述している場合 (つまり、関数テンプレートまたはクラス テンプレートにいる場合) にキーワードが必要であり、型であることがわかっていない可能性があるテンプレート パラメーターに依存する識別子を参照している必要があります。テンプレート コードで型として解釈されます。

あなたの例ではtypename T::Type、定義 #1 で使用します。これT::Typeは、テンプレート パラメーターに依存し、Tそれ以外の場合はデータ メンバーである可能性があるためです。

テンプレート定義の一部として型であると宣言されているためtypename T、定義 #2では必要ありません。T

于 2009-08-08T00:19:43.793 に答える