C++ typename の 2 つの使い方

C++ のテンプレートでは typename キーワードを使います。 ただ、typename はよく使うテンプレートパラメーター以外のところでも必要になってくることがあります。
そこで、今回は typename の使い方について紹介します。

テンプレートパラメーターでの typename

まずはよくあるテンプレートパラメーターでの使用例です。
 template <typename T>
 class Point
 {
     T x_;
     T y_;
      :
テンプレートのパラメーター T が 型であることを宣言 するために typename が使われています。


ここでは typename の代わりに class を使うこともできます。 どちらを使っても違いは何もありません

個人的には次のように使い分けています。

キーワード 使用するケース
typename パラメーターとして基本型をいれることを想定
class それ以外

ただ、基本型を含めてすべての型はクラスとして考えるべき という意見の人などもいて、 どっちを使うかは個人の好みやコーディング規約で決めてください。

階層を持つテンプレートのための typename

次にテンプレートパラメーター以外での使い方です。

例として、先ほどの点クラスの配列(vector)を持つ多角形(Polygon)クラスを考えてみます。

typename.cpp:
 template <typename T>
 class Polygon
 {
     std::vector< Point<T> > points_;
 
   public:
     using value_type = T;
     using size_type = typename std::vector< Point<T> >::size_type;
     using iterator = typename std::vector< Point<T> >::iterator;
     using const_iterator = typename std::vector< Point<T> >::const_iterator;
 
     size_type size() const { return points_.size(); }
     
     iterator begin() { return points_.begin(); }
     iterator end()   { return points_.end(); }
     const_iterator begin() const { return points_.begin(); }
     const_iterator end()   const { return points_.end(); }
     :
vector と同じような機能が欲しいので、vector のメソッドを委譲して使っています。
イテレーターを使うときなど、いちいち std::vector< Point<T> >::iterator と書くのが面倒なので、 using を使って別名保存しています。
こういった using の使い方を知らなかったという人も typedef の上位互換だと思ってください。


1 つめの using に対して特に問題はありません。
2 つ目以降は typename を付けています。 これがテンプレートパラメーター以外の typename です。 これを付けていないとコンパイルが通りません。
typename.cpp:38:23: error: need 'typename' before 'std::vector<Point<T> >::size_type' because 'std::vector<Point<T> >' is a dependent scope
     using size_type = std::vector< Point<T> >::size_type;
上記は g++ のコンパイルエラーメッセージですが、分かりづらいので、もう少し説明してみます。
T はテンプレートパラメーターなので、不確定です。 そのため Point<T> も不確定なので、std::vector<???>::size_type という形です。
"クラス名::xxxx" という形式は型だけでなく、定数にも使います。 そのため、型かどうかハッキリしないものに対して別名定義である using(typedef) を使うと、コンパイルエラーとなってしまいます。

コンパイルを通すには typename を記述して、次にくるのが型だとコンパイラーに伝える必要があります。

テンプレートをいろいろ使っていくと、 テンプレートクラスをメンバーに持ったテンプレートクラスのように階層を持つテンプレートというのが出てきます。 そういった場合、この型だということを宣言する typename の使い方も覚えておく必要があります。
  typename Foo<T>::xxxx

参考

スポンサーサイト



 
このページをシェア
アクセスカウンター
アクセスランキング
[ジャンルランキング]
コンピュータ
31位
アクセスランキングを見る>>

[サブジャンルランキング]
プログラミング
5位
アクセスランキングを見る>>
カレンダー(アーカイブ)
プルダウン 降順 昇順 年別

05月 | 2017年06月 | 07月
- - - - 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 -


はてな新着記事
はてな人気記事
ブロとも申請フォーム
プロフィール

yohshiy

Author:yohshiy
職業プログラマー。
仕事は主に C++ ですが、軽い言語マニアなので、色々使っています。

はてブ:yohshiy のブックマーク
Twitter:@yohshiy

サイト紹介
プログラミング好きのブログです。プログラミング関連の話題や公開ソフトの開発記などを雑多に書いてます。ただ、たまに英語やネット系の話になることも。