The Super Programming Technique
§4.CompileTimeProgramming 【前編】
List-1.1からnまでの合計を求める
テンプレートの部分的な定義がある場合、もっとも適切なものが優先して適用されます。
このことを利用して、以下のように再帰的に計算することができます。
template <int n> struct Total; // 合計を再帰的に定義 // その1. total(0) = 0; // その2. total(n) = total(n-1) + n; // ※ Totalテンプレートの一般的な定義 |
この合計する部分は、コンパイラが計算する部分であって実際のコードに1から100まで加算するコードは存在しません。
コンパイル時点で5050が計算されます。
まるで手品か、単なるパズルかのようですが、実際、このようなコンパイル時プログラミングを利用することによって、クラスライブラリLokiでは、ダブルディスパッチを可能にしています。C++の上級プログラマならば知っておかなければならない技法でしょう。
それはともかく、いまはお遊び感覚で、もう少しコンパイル時プログラミングの世界を覗いてみましょう。
List-2.nの階乗を求める
これはList-1とほぼ同じだから難しくは無いでしょう。
template <int n> struct Factorial; // 階乗を再帰的に定義 // その1. Factorial(0) = 1; template <> struct Factorial<0> { enum { value_ = 1 }; }; // その2. Factorial(n) = Factorial(n-1) * n; template <int n> struct Factorial { enum { value_ = Factorial<n-1>::value_ * n }; }; void main(){ int nFactorial = Factorial<6>::value_; cout << nFactorial; } |
実行すれば、6の階乗
6!=6×5×4×3×2×1=720
の720が表示されます。
List-3.フィボナッチ数を求める
template <int n> struct f; // フィボナッチ数を再帰的に定義 // その1. f(1) = 1 , f(2) = 1 template <> struct f<1> { enum { value_ = 1 }; }; template <> struct f<2> { enum { value_ = 1 }; }; // その2. f(n) = f(n-1) + f(n-2) template <int n> struct f { enum { value_ = f<n-1>::value_ + f<n-2>::value_ }; }; void main(){ int n = f<7>::value_; cout << n; } |
実行すればf(7)==13が表示されます。
プログラミングの世界は、何が実用になるかわかりにくいです。だから、こういうのをパズルだと馬鹿にせず取り組む姿勢が大切です。
そもそも、プログラム自体が頭脳の体操みたいなものなのですから..。
参考(にすると良い)文献.
1.
『Modern C++ Design』 ISBN4-89471-435-3 アンドレイ・アレキサンドレスク著,村上 雅章訳/株式会社ピアソン・エデュケーション
3,600円+税
参考(にすると良い)ページ.
1.LOKI(Andrei Alexandrescuのページ) :http://www.moderncppdesign.com/
2.LOKI Port(LOKIをVC7でコンパイルが通るように改造したもの):http://www.geocities.com/rani_sharoni/LokiPort.html
3.LOKIを(部分的に)VC6で利用しようという試み。:http://pc.2ch.net/test/read.cgi/tech/1008593126/576-615