C++11のconstexprで遊ぶ

関数呼び出しの結果をコンパイル時に計算し、定数として扱えてしまうconstexprで遊びました。

■constexprの利点

テンプレートメタプログラミングのような難しいテクニックが不要で人間にやさしく、コンパイル速度が速い

■例:数字で表現された文字列の総和


constexpr unsigned int sumNumberStep(const char *p, int index, int len)
{
return index >= len ? 0 : sumNumberStep(p, index + 1, len) + (*(p + index) - '0');
}

constexpr unsigned int sumNumber(const char *p, int len)
{
return sumNumberStep(p, 0, len);
}

// sumNumber("123", strlen("123")); ===> 6

C++11のconstexprはステートメントが書けません(C++14では許可されるらしい)。
つまり、ifやforやwhiteを使えません。

代わりにどうするかというと、ifやswitchは三項演算子、forやwhileは再帰関数呼び出しに置き換えます。
上の例では、カウンタindexが文字列の長さlenに達するまで再帰させています。

ほかにも、変数宣言、仮想関数、new/delete等は禁止だそうです。

■例:CRC32

文字列からCRC32した値をコンパイル時に計算します。
yoshida_eth0さんのブログにあるcrc関数をconstexprに対応させます。


constexpr unsigned int crc32constStep(unsigned int crc, const char *p, int index, int len)
{
return index >= len ? crc : crc32constStep(((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ (*(p + index))) & 0xFF], p, index + 1, len);
}

constexpr unsigned int crc32const(const char *p, int len)
{
return crc32constStep(0xFFFFFFFF, p, 0, len) ^ 0xFFFFFFFF;
}

// crc32const("123", strlen("123")); ===> 0x884863d2

crc32()のループを再帰関数化しただけでconstexpr化できます。

■おまけ:VisualStudioでconstexpr

Visual C++コンパイラはconstexprに対応していません。
2015年発売予定のVisual Studio “14”からの対応です。

Clangやgccは対応済みですが、Windowsの場合Eclipseなど開発環境の移行が必要で、ハードルが高いです。

調べてみると、Clang for WindowsというVisualStudioのプラットフォーム ツールセットにLLVMが使える素晴らしいツールが配布されていました。
今回はClang 3.4.1のClang for WindowsをViualStudio 2013で使いました。
残念ながらiostreamなどのC++ヘッダをincludeするとコンパイルエラーになってしまいましたが、stdio.hは使えました。

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中