强制在编译期间评估常量表达式

几天前,我问编译器决定是否在编译期间计算一个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;
}

如果我被告知是真实的,那么这个代码示例非常实用,因为foobar没有使用constexpr(由于某些原因您不能使用参数rexpr作为参数),所以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如何影响性能? 是否有更好的单线解决方案?


只是为了不把它埋在评论中:

#include <type_traits>

#define COMPILATION_EVAL(e) (std::integral_constant<decltype(e), e>::value)

constexpr int f(int i){return i;}

int main()
{
    int x = COMPILATION_EVAL(f(0));
}

EDIT1:

使用这种方法的一个警告是, constexpr函数可以接受浮点并分配给constexpr浮点变量,但不能将浮点类型用作非类型的模板参数。 此外,其他类型的文字也有相同的限制。

你的lambda会为此工作,但我想你需要一个默认捕获来获得有意义的错误消息,当非constexpr东西传递给函数。 结束std::move是可有可无的。

EDIT2:

Err,你的lambda方法对我不起作用,我只是意识到,它甚至可以工作,lambda不是constexpr函数。 它不应该为你工作。

看起来真的没有办法解决它,只是在本地范围内初始化一个constexpr变量。

EDIT3:

哦,好吧,我的坏,拉姆达的目的只是评估。 所以它正在为此工作。 相反,它的结果是无法遵循另一个编译时间评估。

EDIT4:

在C ++ 17中,lambda现在可以用在constexpr上下文中,所以EDIT2 / EDIT3中提到的限制被删除了! 所以lambda解决方案是正确的。 请参阅此评论以获取更多信息。

链接地址: http://www.djcxy.com/p/68361.html

上一篇: Forcing a constant expression to be evaluated during compile

下一篇: c++11