...ing logging 4.0

はてなブログに移行しました。D言語の話とかいろいろ。

D言語でのテンプレートメタプログラミング

通常,コンパイラプログラミング言語を解釈して実行可能なバイナリに変換します.
これに対して,テンプレートメタプログラミングは,もう一段メタなレベルで,コンパイル時にコンパイラに計算を行わせる手法です.
C++でもテンプレートメタプログラミングを行うことは一応可能で,これがJavaC#にはないアドバンテージになっています.
しかし,最初からテンプレートメタプログラミングを行うことを考慮して設計されたわけではないので,かなりトリッキーな方法になってしまいます.

D言語ではこれをふまえて最初からテンプレートメタプログラミングを行いやすく設計されています.
テンプレートメタプログラミングの入門として有名な,コンパイル時に階乗を求める処理をD言語で書いてみましょう(参考:オフィシャルサイトの日本語訳版).

import std.c.stdio;

template factorial(int n)
{
static if (n != 1)
const factorial = n * factorial!(n-1);
else
const factorial = 1;
}

int main(char[][] args)
{
printf("3! = %d", factorial!(3));
return 0;
}

いったい, factorial はテンプレート関数なのか定数なのか・・・.
不思議なコードですが, factorial!(3) の部分がコンパイル時に再帰的に展開されていって,最後には単なる定数 6 になります.
従って,実行時には,上のコードと下のコードはまったく等価です.

import std.c.stdio;

int main(char[][] args)
{
printf("3! = %d", 6);
return 0;
}

試しに,コンパイラが生成した実行ファイルをコマンドラインから comp コマンドを使って比較してみても,まったく同じでした.
実行ファイルには単に定数が埋め込まれているだけですから,実行時にCPUの能力を消費することはありません.
面白いですね!