"typename"キーワードはいつ必要ですか?

可能重複:
  正式にtypenameは何ですか?
  テンプレートをどこに置く必要があるのですか? typenameのキーワードは?

以下のコードを検討してください:

template
class C {
    struct P {};
    vector
vec; void f(); }; template void C::f() { typename vector
::iterator p = vec.begin(); }

この例で「typename」キーワードが必要な理由は何ですか? 「typename」を指定する必要がある場合は他にもありますか?

45
追加された 著者 Johannes Schaub - litb,

3 答え

短い答え:名前が従属名のネストされた名前を参照するときはいつでも、パラメータが未知のテンプレートインスタンスの中に入れ子になっています。

長い答え:C ++には、値、型、テンプレートという3つのエンティティがあります。それらのすべてが名前を持つことができます。名前だけではエンティティのどの階層であるかは分かりません。むしろ、名前の実体の性質に関する情報は、文脈から推論されなければならない。

この推論が不可能なときはいつでも、それを指定する必要があります:

template  struct Magic;//defined somewhere else

template  struct A
{
  static const int value = Magic::gnarl;//assumed "value"

  typedef typename Magic::brugh my_type;//decreed "type"
 //     ^^^^^^^^

  void foo() {
    Magic::template kwpq(1, 'a', .5);//decreed "template"
   //       ^^^^^^^^
  }
};

Here the names Magic::gnarl, Magic::brugh and Magic::kwpq had to be expliciated, because it is impossible to tell: Since Magic is a template, the very nature of the type Magic depends on T -- there may be specializations which are entirely different from the primary template, for example.

What makes Magic::gnarl a dependent name is the fact that we're inside a template definition, where T is unknown. Had we used Magic, this would be different, since the compiler knows (you promise!) the full definition of Magic.

(これを自分でテストしたい場合は、使用できる Magic のサンプル定義を次に示します。簡潔にするためにspecializeで constexpr を使用してください。コンパイラは、静的メンバ定数の宣言を古いスタイルのpre-C ++ 11フォームに自由に変更することができます。)

template  struct Magic
{
  static const T                    gnarl;
  typedef T &                       brugh;
  template  static void kwpq(int, char, double) { T x; }
};
template <> struct Magic
{
 //note that `gnarl` is absent
  static constexpr long double brugh = 0.25; //`brugh` is now a value
  template  static int kwpq(int a, int b) { return a + b; }
};

使用法:

int main()
{
  A a;
  a.foo();

  return Magic::kwpq(2, 3); //no disambiguation here!
}
62
追加された
@Nils: const はC ++ではありません。
追加された 著者 Kerrek SB,
@PaoloM:クラステンプレート A のメンバ関数の定義は、最初の段階で既に解析されている必要がありますので、構文を曖昧にする必要はありません。第2段階では、具体的な型 T のインスタンス化 Magic が実際に kwpq 適切な署名。 (そして編集のおかげで!)
追加された 著者 Kerrek SB,
説明してくれてありがとう。しかし、 Magic :: kwpq という名前はテンプレートパラメータ T に依存しているので、これは第2段階で解決されます 2段階ルックアップ、右か?だから、コンパイラは、その時に kwpq がテンプレートであるかどうかを判断できるようになると、その名前が< i>エンティティの階層?
追加された 著者 Paolo M,

iteratorP の依存型なので、 typename キーワードが必要です。コンパイラは、 iterator が値または型を参照しているかどうかを推測することはできませんので、 typename テンプレートの引数に依存する型がある場合は常に、型または値が有効であるコンテキストで必要です。たとえば、基底クラスは型でなければならないので、基底クラス typename は不要です。

同じ主題では、 template というキーワードがあります。これは、依存名が値ではなくテンプレート関数であることをコンパイラに知らせるためです。

10
追加された

typenameキーワードは、型名がテンプレートパラメータに依存する場合に必要です(コンパイラは識別子の意味( type または value )最初のパスで完全なシンボルテーブル)。


Not in the same meaning, and a bit less common, the lone typename keyword can also be useful when using generic template parameters: http://ideone.com/amImX

#include 
#include 
#include 

template 
7
追加された
私は前に "孤独なtypename"について知りませんでした、それはクールです!
追加された 著者 Remy Lebeau,