C++ クラステンプレートについて 書いて覚えるための初心者自己中記事
その前に typename ってなんだ?
と思って確認した。
~~~~~~~~~
不明な識別子が型であることをコンパイラに通知します。
~~~~~~~~~
納得。
基本的なことをわかってなかったから理解するのが難しくなってしまう。
型ごとに定義を変更したクラステンプレートのことを
クラステンプレートの特殊化
という。
template <typename TYPE>//大本のテンプレートクラス class Limits { public: static const TYPE MIN; //TYPE型の最小値 static const TYPE MAX; //TYPE型の最大値 }; template<>//テンプレート引数が unsigned short だった場合はこれ class Limits<unsigned short> { public: static const unsigned short MIN = 0; static const unsigned short MAX = USHRT_MAX; }; //別のやり方 クラステンプレート引数が int だった場合はこれ template<> const int Limits<int>::MIN = INT_MIN; template<> const int Limits<int>::MAX = INT_MAX; template<typename TYPE>//この関数テンプレートに型を渡すとその型のクラステンプレートを呼び出してくれる。 void ShowMinMax() { cout << "TYPE : " << typeid(TYPE).name() << endl << "MIN : " << Limits<TYPE>::MIN << endl << "MAX : " << Limits<TYPE>::MAX << endl; } int main() { ShowMinMax<int>(); ShowMinMax<unsigned short>(); system("pause"); }
template< > 引数部分を何も書かず
クラス名の引数部分に特定の型を入れておくと
クラステンプレートを呼び出した時に該当するものが呼ばれるのかな?
二つのやり方を書いたけど、
クラス丸ごとのほう
クラス宣言で特殊化
単発のほう
実体定義で特殊化
と言われる。
クラス宣言で特殊化のほうは別のクラスを作ってる感があるけど、
実体定義で特殊化のほうは、大本のクラステンプレートに代入している感があるなぁ。
いや、MINとMAXでそれぞれ実体を作っている感じか。
全体的にクラステンプレートをオーバーロードしてるっぽい印象。
これって、もうなんか、クラステンプレート内で型の判定して結果を分岐させたりとかじゃダメなのかな?
クラス宣言で特殊化の場合は大本のクラステンプレートのメンバは全消しされる。
実体定義での特殊化の場合は、関わったメンバのみで、関わってないメンバは有効。
引数が複数ある場合に片方だけ指定した特殊化も出来る。
template<typename TYPE1, typename TYPE2> class Hoge { }; template<typename TYPE1>//第二引数がint の場合はこっち class Hoge<TYPE1, int> { };
さらに
template<typename TYPE1, typename TYPE2> class Hoge { }; template<typename TYPE1>//第一、第二引数の型が同じ場合はこっちにくる class Hoge<TYPE1, TYPE1> { };
そして引数が一つのクラステンプレートを
引数が二つあるクラステンプレートを引数に指定して特殊化
//何かしら二つ引数をとるテンプレートクラスAB template<typename AA, typename BB> class AB { public: AB(const AA& aba, const BB& abb) :aa(aba), bb(abb){} const AA aa; const BB bb; }; //テンプレートクラスHoge template<typename TYPE1> class Hoge { }; //テンプレートクラスHogeを特殊化 //引数に上記の「引数を二つとるテンプレートクラスAB」を指定 template<typename A,typename B> class Hoge<AB<A, B>> { public: Hoge(const A& a, const B& b) :a_b(a, b) {} void Show() { cout << a_b.aa << endl; cout << a_b.bb << endl; } private: AB<A, B> a_b; }; int main() { Hoge< AB<int, const char*> > p(1, "hoge"); p.Show(); system("pause"); }
ややこしい。
いつか使うんだろうか・・・。
関数テンプレートの特殊化はクラスでいうところの
クラス宣言で特殊化
のほうだけ。
単体定義で特殊化は出来ない。
っていうか、関数テンプレートってクラスと違ってそもそも単体だと思うし。
なんかここまでくるとやっぱりオーバーロードでいいじゃんね。
いや、そういう話ではないのか。
プログラマーはこういうのを使いこなしてプログラムを作っているんだろうか・・・。すごいなぁ。
活用方法が全くわからない。
ここまで。