TMPの練習にと、FizzBuzzしたり素数並べたりしてるとこで
template<int N, int D = N - 1> struct Test
っていう形に出会った。パッと見第2引数が常にN - 1になるかと思ったが、実はそうではなかった。
テンプレートの第2引数に何も指定されていなければD=N - 1になり、何か引数が与えらていればDはその値になるようだ。
例えば以下のコードの出力は
9
5
10
になる。
#include <iostream>
template<int N, int D = N - 1> struct Test{
Test(){
std::cout << D << std::endl;
}
};
template<int N> struct Test<N, 1>{
Test(){
std::cout << N << std::endl;
}
};
int main()
{
Test<10>();
Test<10, 5>();
Test<10, 1>();
}
ちなみに3つ目は部分特殊化
2014年9月27日土曜日
2014年9月8日月曜日
テンプレートメタプログラミングが難しい
Effective C++を読んでいたら最後の法でテンプレートメタプログラミング(TMP)というのが出てきました。
以下の階乗を計算するプログラムがTMPの初歩的なプログラムらしいです。
#include <iostream>
template<unsigned n>
struct Factorial {
enum { value = n * Factorial<n - 1>::value };
};
template<>
struct Factorial<0> {
enum { value = 1 };
};
int main()
{
std::cout << Factorial<5>::value << std::endl;
std::cout << Factorial<10>::value << std::endl;
getchar();
}
このコードを見てよくわからなかったのは
・enumってなんか意味あるの?
・Factorialっていつ計算されるの?
でした。
static const unsigned value = n * Factorial<n - 1>::value;
と書いても動きましたが、こっちはコンパイラによってはエラーになるらしい。
TMPでは、このような静的な計算がコンパイル時に行われるため、計算が高速化するらしいです。
ほかにTMPの効用としては
しかし、実際どうやってTMPで書いていったらいいかわからんです
以下の階乗を計算するプログラムがTMPの初歩的なプログラムらしいです。
#include <iostream>
template<unsigned n>
struct Factorial {
enum { value = n * Factorial<n - 1>::value };
};
template<>
struct Factorial<0> {
enum { value = 1 };
};
int main()
{
std::cout << Factorial<5>::value << std::endl;
std::cout << Factorial<10>::value << std::endl;
getchar();
}
このコードを見てよくわからなかったのは
・enumってなんか意味あるの?
・Factorialっていつ計算されるの?
でした。
enumってなんか意味あるの?
enumハックというやつらしいです。コンパイル時にクラス内で定数が必要になるときに使うそうです。static const unsigned value = n * Factorial<n - 1>::value;
と書いても動きましたが、こっちはコンパイラによってはエラーになるらしい。
Factorialっていつ計算されるの?
コンパイル時にされる。普通に本文に書いてあったのですが、文章ってあまり頭に入ってこないですね。コード見たときになんやこれ、って思って悩んでしまいました。TMPでは、このような静的な計算がコンパイル時に行われるため、計算が高速化するらしいです。
ほかにTMPの効用としては
エラーがコンパイル時にみつかる
たとえば Factorial<20> とかにすると値が大きくなりすぎてエラーをはくTMPはチューリング完全であることが証明されている
要はどんな計算でもTMPで書けることが保障されているらしい・・・しかし、実際どうやってTMPで書いていったらいいかわからんです
登録:
コメント (Atom)