数日前、コンパイラがコンパイル時に constexpr 関数を計算するかどうかを決定する基準を尋ねました。
コンパイル時に constexpr 関数が評価されるのはいつですか?
結局のところ、constexpr は、すべてのパラメーターが定数式であり、それを割り当てる変数も定数式である場合にのみ、コンパイル時に評価されます。
template<typename base_t, typename expo_t>
constexpr base_t POW(base_t base, expo_t expo)
{
return (expo != 0 )? base * POW(base, expo -1) : 1;
}
template<typename T>
void foobar(T val)
{
std::cout << val << std::endl;
}
int main(int argc, char** argv)
{
foobar(POW((unsigned long long)2, 63));
return 0;
}
私が言われたことが本当なら、このコード例は非常に実用的ではありません.コンパイル時に計算します。コンパイル時の評価を強制するための明白な解決策は次のとおりです。
auto expr = POW((unsigned long long)2, 63);
foobar(expr);
ただし、これにより、コンパイル時に constexpr が確実に評価されるようにするたびに、追加のコード行を使用する必要がなくなります。これをもう少し便利にするために、次の疑わしいマクロを考え出しました。
#define FORCE_CT_EVAL(func) [](){constexpr auto ___expr = func; return std::move(___expr);}()
foobar(FORCE_CT_EVAL(POW((unsigned long long)2, 63)));
正常に動作しているにもかかわらず、何かがおかしいように感じます。匿名ラムダの作成はパフォーマンスに影響しますか? 右辺値参照によって返されると、実際に式が関数パラメーターに移動しますか? std::move はパフォーマンスにどのように影響しますか? これに対するより良いワンライナーソリューションはありますか?