C++におけるtypenameの役割

C++に限ったことではないが, 基礎をちゃんとやらなかったので今更typenameというものを勉強し始めた.

そもそもtypenameはテンプレート引数を指定するときに使うばかりだったが, 正しくは以下のような宣言の仕方を先に学ぶべきである.

template<class T, std::size_t SIZE>
class CBuffer
{
  CBuffer()
  {
    ;
  }

private:

  T data_[SIZE];
};

CBuffer<double, 10> buf;

テンプレート引数にはデータ型だけでなく値そのものも書くことができる. つまり通常の関数と同様に型と引数名をセットで与えるのが常道であるが, 型自体が引数となる場合があり, その場合にその型名としてclassだとかtypenameだとか書くわけである.

http://www.geocities.jp/ky_webid/cpp/language/028.html

もう1つtypenameの役割として型名であることを明示するという働きがある.

#include <vector>
#include <iostream>
#include <boost/shared_ptr.hpp>


template<typename Tcont_>
class ContainerWrapper
{
public:

  typedef Tcont_ container_type;
  typedef typename Tcont_::size_type size_type;

  ContainerWrapper(boost::shared_ptr<Tcont_> cont)
    : cont_(cont)
  {
    ;
  }

  // Tcont_::size_type size() const /// これだとエラー
  // typename Tcont_::size_type size() const /// これはOK
  size_type size() const /// これもOK
  // container_type::size_type size() const /// これはエラー
  {
    return (cont_)->size();
  }

private:

  boost::shared_ptr<Tcont_> cont_;
};

int main()
{
  typedef std::vector<int> container_type;
  boost::shared_ptr<container_type> ptr(new container_type());
  ContainerWrapper<std::vector<int> > cw(ptr);
  std::cout << cw.size() << std::endl;
}

対して意味のない例だが, ようするにTcont_がclassなり型なりであることはわかったが, Tcont_::size_typeが何者かは不明なので, やはり型であるということを明示するためにtypenameを前につけてやる必要がある. そうしないと"error: need `typename' before `Tcont_::size_type' because `Tcont_' is a dependent scope"などと言われてしまう.

もうちょっと筋の良い方法としてはあらかじめtypenameをつけてsize_typeをtypedefをしておくことだと思う. これでtypenameを意識する必要がなくなる.

あほっぽいが, Tcont_をtypedefしておいてもsize_typeをとってくるときにはやはりtypenameが必要である. 紛らわしいのでTcont_をtypedefで別名にするのはあまり好ましくないように思ったが如何か.

http://www.fides.dti.ne.jp/~oka-t/cpplab-template-4.html