在编译期间或运行时确定“constexpr”的执行

Determine `constexpr` execution - during compilation or at runtime?

本文关键字:constexpr 执行 编译 运行时      更新时间:2023-10-16

有没有办法在编译阶段和运行时实现constexpr函数的不同行为?

考虑以下示例(使用D: static if的理论特征):

constexpr int pow( int base , int exp ) noexcept
{
    static if( std::evaluated_during_translation() ) {
        auto result = 1;
        for( int i = 0 ; i < exp ; i++ )
            result *= base;
        return result;
    } else { // std::evaluated_during_runtime()
        return std::pow( base , exp );
    }
}

如果没有,是否有办法将constexpr限制为仅在编译时?

不,没有这样的方法。

对不起。

N3583是一篇建议进行更改以满足您的要求的论文。

在C++20之前,这是不可能的。C++20然后添加了std::is_constant_evaluated,这正是用于这个用例的:

constexpr int pow(int base, int exp) noexcept
{
    if (std::is_constant_evaluated())
    {
        auto result = 1;
        for (int i = 0; i < exp; i++)
            result *= base;
        return result;
    } 
    else
    {
        return std::pow(base, exp);
    }
}

请注意,if语句本身是而不是constexpr。如果是,那么整个else arm将从函数中删除,并且它将始终运行If arm,无论是在编译时还是在运行时。对于一个普通的if语句,基本上可以得到两个函数。在编译时运行的

constexpr int pow(int base, int exp) noexcept
{
    auto result = 1;
    for (int i = 0; i < exp; i++)
        result *= base;
    return result;
}

一个在运行时被编译并运行的:

constexpr int pow(int base, int exp) noexcept
{
    return std::pow(base, exp);
}

编译器可以安全地删除if arm,因为它可以证明它在运行时是不可访问的。相当整洁。