メタ関数で型を変換する
C++テンプレートテクニック 4-3
テンプレートメタプログラミング - (void*)Pないとの続きです。
今度は型を変換するメタ関数の登場です。
#include <iostream> using std::cout; using std::endl; template<class T> struct types { typedef T type; }; int main () { types<int>::type i; return 0; }
このコードは、インスタンス化されると
int main () { int i; return 0; }
に置き換わります。例によって例の如く、これだけじゃだからどうした?っていう話ですね。そこで型の変換を行ってみます。
ある型を参照型に変換する処理を考えてみます。
#include <iostream> using std::cout; using std::endl; template<class T> struct types { // 参照型に変換 typedef T& type; }; int main () { int i = 100; types<int>::type j = i; i = 300; cout << j << endl; return 0; }
$ main 300
となります。
ただしこのままだと、もしtypes<>にint&型を渡した場合int&&に変換されてしまい、コンパイルエラーになります。
main.cpp main.cpp(6) : error C2529: 'type' : 参照への参照は無効です。 main.cpp(16) : コンパイルされたクラスの テンプレート のインスタンス化 'types<T>' の参照を確認してください with [ T=int & ]
なので特殊化を利用し、参照型が渡された場合はそのまま返すようにします。
template<class T> struct types { typedef T& type; }; // 参照型が渡された場合だけ特殊化。そのまま返す template<class T> struct types<T&> { typedef T& type; };
これで完成です。
さて今度はある型からconst型を外す処理を考えてみます。
#include <iostream> using std::cout; using std::endl; // const付いてない場合はそのまま template<class T> struct types { typedef T type; }; // const付いてる場合だけ特殊化。外して返す template<class T> struct types<const T> { typedef T type; }; int main () { types<const int>::type i = 100; // 書き換え可能。エラーにならない。 i = 300; return 0; }
基本的には同じような感じですね。
型変換のメタ関数を色々用意しておけば、各所でtypedefせずに済むのでかなり便利かもしれません。