Template

本物のページはこちら→template

定義

これを使ったからといって手書きのコード(hard-written code)と比べて余分な実行時オーバーヘッドを生まないようにするためのコンパイル時メカニズムである。
Javaで同じようなことをしたかったらジェネリックスのページヘ。

テンプレートの利点

  • テンプレートはマクロに比べ型安全である。
  • 関数形式のマクロでよく起こるエラーをテンプレートでは回避できる。
  • マクロの欠点:1論理行に収めなければならない(規模の大きいマクロは書くのが面倒)

コンパイル上の注意

テンプレート関数は、インラインでなければ、定義することができません。
テンプレートを使う場合はその実装もヘッダで書かないといけない。

普通のクラスで、ある特定のメンバ関数だけテンプレート化したい場合、
以下のコードは文字を数字に変換する関数を例にあげます

NGな書き方 OKな書き方
.hファイルにて
template<typename T> void string2num(std::string str, T* val);
    template<typename T>
    void string2num(std::string str, T* val) {
        std::stringstream sstream;
        sstream << str;
        sstream >> *val;
    }
.cppファイルにて
    template<typename T>
    void クラス名::string2num(std::string str, T* val) {
        std::stringstream sstream;
        sstream << str;
        sstream >> *val;
    }
.cppには何も書かない!
NGな書き方をすると、どうなるのかというと、
一応コンパイルは通って挙動も想定どおりにはなるのですが、
IntelliSenseでひっかかってしまい、Visual Studioで赤い波線が引かれてしまいます。
エラーの内容はこうです
template-error.png

基本

違う型でも同じコードが利用できるのが利点。
データ形式に依存しないコンピュータプログラミング方式でジェネリックプログラミングの一種になる。

template<typename インスタンス化する型> 
class List 
{ 
   /* クラスの中身 */
};

テンプレート引数

template <ここが引数>

この引数のことを一般的にはテンプレート引数と呼ぶがテンプレート型パラメータとも呼ばれることがある。

テンプレート引数の構文の曖昧性

テンプレート引数の中に大小、という意味での>を使いたい場合

は、()でくくらなければならない。

T<a>b>(0);//構文エラー
T<(a>b)>(0);//ok

末尾の>を寄せ過ぎるとエラーになる

list<vector<int>> lv1;//エラー >>は右シフト演算子だと思われる。
list< vector<int> > lv2;//ok

続きはテンプレート引数のページへ

擬似的にtemplateするテクニック(メタ型)

opencvのCvArrみたいに任意の配列

typedef void CvArr;

これ、メタ型っていうの?
IplImage*でもCvMat*でも引数に取れる。
ここの配列型は、実行時にヘッダの最初の4バイトを解析することで決定されてるんだって

定義

これを使ったからといって手書きのコード(hard-written code)と比べて余分な実行時オーバーヘッドを生まないようにするためのコンパイル時メカニズムである。
Javaで同じようなことをしたかったらジェネリックスのページヘ。

テンプレートの利点

  • テンプレートはマクロに比べ型安全である。
  • 関数形式のマクロでよく起こるエラーをテンプレートでは回避できる。
  • マクロの欠点:1論理行に収めなければならない(規模の大きいマクロは書くのが面倒)

コンパイル上の注意

テンプレート関数は、インラインでなければ、定義することができません。
テンプレートを使う場合はその実装もヘッダで書かないといけない。

普通のクラスで、ある特定のメンバ関数だけテンプレート化したい場合、
以下のコードは文字を数字に変換する関数を例にあげます

NGな書き方 OKな書き方
.hファイルにて
template<typename T> void string2num(std::string str, T* val);
    template<typename T>
    void string2num(std::string str, T* val) {
        std::stringstream sstream;
        sstream << str;
        sstream >> *val;
    }
.cppファイルにて
    template<typename T>
    void クラス名::string2num(std::string str, T* val) {
        std::stringstream sstream;
        sstream << str;
        sstream >> *val;
    }
.cppには何も書かない!
NGな書き方をすると、どうなるのかというと、
一応コンパイルは通って挙動も想定どおりにはなるのですが、
IntelliSenseでひっかかってしまい、Visual Studioで赤い波線が引かれてしまいます。
エラーの内容はこうです
template-error.png

基本

違う型でも同じコードが利用できるのが利点。
データ形式に依存しないコンピュータプログラミング方式でジェネリックプログラミングの一種になる。

template<typename インスタンス化する型> 
class List 
{ 
   /* クラスの中身 */
};

テンプレート引数

template <ここが引数>

この引数のことを一般的にはテンプレート引数と呼ぶがテンプレート型パラメータとも呼ばれることがある。

テンプレート引数の構文の曖昧性

テンプレート引数の中に大小、という意味での>を使いたい場合

は、()でくくらなければならない。

T<a>b>(0);//構文エラー
T<(a>b)>(0);//ok

末尾の>を寄せ過ぎるとエラーになる

list<vector<int>> lv1;//エラー >>は右シフト演算子だと思われる。
list< vector<int> > lv2;//ok

続きはテンプレート引数のページへ

擬似的にtemplateするテクニック(メタ型)

opencvのCvArrみたいに任意の配列

typedef void CvArr;

これ、メタ型っていうの?
IplImage*でもCvMat*でも引数に取れる。
ここの配列型は、実行時にヘッダの最初の4バイトを解析することで決定されてるんだって[[bibliography]]
label
テンプレートの実装をヘッダに書かなければならない理由 (void*)Pないと

[[/bibliography]]

サポートサイト Wikidot.com