#42 typenameの2つの意味を理解する.

Effective C++ 42項の内容です.

typenameの2つの用法

この項で述べられているtypenameの2つの意味ですが,下記です.

1. テンプレートパラメータの宣言として使う.
2. 「C++では,テンプレートパラメータ内部にあるネストされた依存型名はそのままでは型名と解釈されない」ため,型名として指示するために使う.

なんだかよくわからない日本語になってしまいましたが,いつもの如くサンプルコードで実験していきます.

1. テンプレートパラメータの宣言として使う.

まずは自明な?というか,一番ベーシックなtypenameの使い方である,「テンプレートパラメータとしての使用」です.STLベクターみたいに,クラスや関数などが扱う型をintとかdoubleとか予めかっちり決めるのではなく,ライブラリを使う人が決めることができます.サンプルコードは2つ書きましたが,この使い方の場合は,typenameを使っても,classを使ってもどちらでもOKです.

template<class T>
class TemplatedClass1 {
public:
  T member;
};

template<typename T>
class TemplatedClass2 {
public:
  T member;
};

int main(int, char**) {

  TemplatedClass1<int> tc1;
  TemplatedClass2<int> tc2;

  return 0;
}

2. 「C++では,テンプレートパラメータ内部にあるネストされた依存型名はそのままでは型名と解釈されない」ため,型名として指示するために使う.

わけわからない日本語になってしまってますが,サンプルコードをまず書きます.


#include <iostream>

class TypeClass {
public:
  enum value_type { val1 = 100, val2 };  // <-- テンプレートパラメータ内部にある,ネストされた依存型名.
  static const int value_type = 0;
};

template<typename T>
class TemlatedClass {
public:
  void print() {
    //T::value_type *val1;
    typename T::value_type val1 = T::value_type::val1;  // <-- テンプレートパラメータ内部にある,ネストされた依存型名はそのままでは型名と解釈されないので,typenameをつける.
    int val2 = T::value_type;
    std::cout << val1 << std::endl;
    std::cout << val2 << std::endl;
  }
};

int main(int, char**) {

  std::cout << "chap_7th_42_1.cpp" <<  std::endl;

  TemlatedClass<TypeClass> tc;
  tc.print();

  return 0;
}

上記の例の様に,テンプレートパラメータとして渡されるクラス「TypeClass」の内部で,下記の2つが同時に宣言されています.
enum value_type という型.
・static const int value_typeという静的定数変数.

この時,このクラスをテンプレートパラメータとして使う TemplatedClass を考えてみます.ここで,上記のサンプルコードにprint()という関数を作りましたが,コメントアウトした下記の表記を見てみます.

//T::value_type *val1; <- この書き方はアウト!value_typeがTypeClassの静的変数のことをいっているのか,内部定義されたenumのことを言っているのかわからない.

T::value_type の解釈の仕方が2つあります.
1.テンプレート型の内部で宣言されている enumvalue_type
2.テンプレート型の内部で宣言されている静的定数変数の value_type
1の解釈で一行を読み取ると,val1はenum変数のポインタ.2の解釈で一行を読み取ると,掛け算をしている行になります.

ということで,この曖昧さを取り除くために,「ネストされた依存名の型を使って宣言したい場合は,先頭に typename をつける.」となります.

ちなみに,上記のコードを実行すると下記の所望の実行結果が得られていることがわかります.

chap_7th_42_1.cpp
100 <- enum value_type::val1の値が出ている.
0 <- 静的定数変数 TypeClass::value_typeの値が出ている.