ゆとりーなの日記

日記的な事を書いて行くと思はれる

typenameがいるときいらないときVC++編

あくまでVC++のみでのお話ですので、ここで付けなくてもいいと言われても、よいこのみんなは真似しないでください。

テンプレート関数内部の変数宣言の型ではtypename不要

次のようなコードでは警告もエラーも一切出ません。

struct hoge {
  typedef int type;
};

template <typename T>
void foo1() {
  const T::type a = 0;
}

int main() {
  foo1<hoge>();
}

テンプレート関数内部でのキャストでもtypename不要

これも大丈夫です。

struct hoge {
  typedef int type;
};

template <typename T>
void foo1() {
  int a = static_cast<T::type>(0);
}

int main() {
  foo1<hoge>();
}

テンプレート関数内部でのtypedefでもtypename不要

これでも大丈夫です。

struct hoge {
  typedef int type;
};

template <typename T>
void foo1() {
  typedef T::type *type;
  type p = nullptr;
}

int main() {
  foo1<hoge>();
}

戻り値の型ではtypename必須

次のようなコードがあると、「'T::type' : 依存名は型ではありません。」という警告と共に「構文エラー : ';' が、識別子 'foo2' の前に必要です。」、「型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません」からの「直前のエラーを修復できません。コンパイルを中止します。」と出てFatal K.O.されます。

template <typename T>
T::type foo2() {
  return 0;
}

型演算でもtypename必須

次のような単純な型演算でもtypenameがないと「'T::type' : 依存名は型ではありません。」という警告、「構文エラー : ';' が、識別子 'type' の前に必要です。」というエラー、「access 宣言の使用は避けてください; メンバー using 宣言を使用してください。」という警告の後、「型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません」と出てエラーになります。

template <typename T>
struct hogehoge {
  typedef T::type type;
};

template引数でもtypename必須

次のようにテンプレート引数に持ってくる時でもtypenameがないと「'T::type' : 依存名は型ではありません。」の警告、「構文エラー : 識別子 'type'」のエラーとなります。

template <typename T, T::type N>
struct hogehoge {
};

テンプレートクラスのメンバ変数でもtypename必須

関数内部の自動変数と違い、メンバ変数ではtypenameがないと型演算のときと同様の警告、エラーが出ます。

template <typename T>
struct hogehoge {
  T::type a;
};

まとめ

見た感じだと、関数内部だとtypenameのチェックが行われないのではないかという様な気がしないこともないです。