几天前我询问编译器根据哪些标准来决定是否在编译时计算constexpr函数。
正如所发现的那样,只有当所有参数都是常量表达式,您要分配的变量也是常量表达式时,constexpr才会在编译时计算。
参考链接:When does a constexpr function get evaluated at compile time?
正如所发现的那样,只有当所有参数都是常量表达式,您要分配的变量也是常量表达式时,constexpr才会在编译时计算。
参考链接:When does a constexpr function get evaluated at compile time?
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;
}
如果我听到的是真的,那么这个代码示例非常不实用,因为 foobar 不接受 constexpr(由于某些原因,您无法将 constexpr 用作参数),POW 在运行时进行评估,尽管可以在编译时计算它。 强制编译时评估的明显解决方案是:
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)));
尽管它完全可以正常工作,但我感觉好像有些不对劲。创建匿名lambda函数会影响性能吗?通过rvalue引用返回是否实际上将表达式移动到函数参数中?std::move如何影响性能?有没有更好的一行代码解决方案?
xvalue
,此外...如果你传递变量而不是字面值作为参数,我认为它不能正常工作,因为lambda需要捕获它们。现在的方式会发出有关无法捕获变量的错误,对编译评估执行没有太多建议性。 - oblitum#define COMPILATION_EVAL(f, ...) (std::integral_constant<decltype(f(__VA_ARGS__)), f(__VA_ARGS__)>::value)
。 - oblitumconst auto p=POW((unsigned long long)2, 63); foobar(p);
,gcc 也会这样做。 - Marc Glisse