在编译期间或运行时确定`constexpr`执行?

non*_*ion 14 c++ constexpr c++14

有没有办法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 );
    }
}
Run Code Online (Sandbox Code Playgroud)

如果没有,有没有办法限制constexpr只编译时间?

Yak*_*ont 6

不,没有这样的方式.

抱歉.

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


Tim*_*imo 5

在 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,该if语句本身不是 constexpr。如果是这样,则整个 else 臂将从函数中删除,并且无论是在编译时还是运行时,它都将始终运行 if 臂。使用普通的 if 语句,您基本上会得到两个函数。一个在编译时运行的:

constexpr int pow(int base, int exp) noexcept
{
    auto result = 1;

    for (int i = 0; i < exp; i++)
        result *= base;

    return result;
}
Run Code Online (Sandbox Code Playgroud)

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

constexpr int pow(int base, int exp) noexcept
{
    return std::pow(base, exp);
}
Run Code Online (Sandbox Code Playgroud)

编译器可以安全地删除 if 臂,因为它可以证明它在运行时不可访问。很简约。