一般的にC++はCより遅いと言われています.
事実,C++のプログラムでは仮想関数テーブルやRTTI(実行時型情報),例外処理等
明らかにパフォーマンスに影響しそうなコードが現れます.
しかし,関数オブジェクトやテンプレートをうまく使えばCにはできない高速化
を行う事が出来る事も事実です.そんな例を紹介してみたいと思います.
テンプレートを使うとコンパイル時にコンパイラがコードを自動生成してくれます.
これを利用した高速化の紹介です.
これはErwin Unruh氏が考案した,テンプレートを使った素数を計算するコードです.
// Prime number computation by Erwin Unruh
template <int i> struct D { D(void*); operator int(); };
template <int p, int i> struct is_prime {
enum { prim = (p==2) || (p%i) && is_prime<(i>2?p:0), i-1> :: prim };
};
template <int i> struct Prime_print {
Prime_print<i-1> a;
enum { prim = is_prime<i, i-1>::prim };
void f() { D<i> d = prim ? 1 : 0; a.f();}
};
template<> struct is_prime<0,0> { enum {prim=1}; };
template<> struct is_prime<0,1> { enum {prim=1}; };
template<> struct Prime_print<1> {
enum {prim=0};
void f() { D<1> d = prim ? 1 : 0; };
};
#ifndef LAST
#define LAST 18
#endif
main() {
Prime_print<LAST> a;
a.f();
}
このコードは実はコンパイルが通りません.
しかし,コンパイルするとエラーメッセージとして素数が表示されます.
つまり,素数をプログラムの実行時でなくコンパイル時に求める事が出来るのです.
これから,引数が定数の場合,複雑な計算の多くはコンパイル時に行ってしまう事ができるというのです.
g++でのコンパイル結果を紹介しておきます(grepでいらないエラーをはぶいてあります).
$ g++ prim.cpp -DLAST=30 | & grep init prim.cpp:12: error: initializing argument 1 of `D<i>::D(void*) [with int i = 29]' prim.cpp:12: error: initializing argument 1 of `D<i>::D(void*) [with int i = 23]' prim.cpp:12: error: initializing argument 1 of `D<i>::D(void*) [with int i = 19]' prim.cpp:12: error: initializing argument 1 of `D<i>::D(void*) [with int i = 17]' prim.cpp:12: error: initializing argument 1 of `D<i>::D(void*) [with int i = 13]' prim.cpp:12: error: initializing argument 1 of `D<i>::D(void*) [with int i = 11]' prim.cpp:12: error: initializing argument 1 of `D<i>::D(void*) [with int i = 7]' prim.cpp:12: error: initializing argument 1 of `D<i>::D(void*) [with int i = 5]' prim.cpp:12: error: initializing argument 1 of `D<i>::D(void*) [with int i = 3]' prim.cpp:12: error: initializing argument 1 of `D<i>::D(void*) [with int i = 2]'
後日