2

在 clang 下,以下函数为尾递归函数生成目标代码:

template<typename T>
constexpr bool is_prime(T number, T limit, T counter)
{
    return counter >= limit
        ? number % limit != 0
        : number % counter
            ? is_prime(number, number / counter, counter + 2)
            : false;
}

template<typename T>
constexpr bool is_prime(T n)
{
    return n == 2 || n == 3 || n == 5
        ? true
        : n <= 1 || n % 2 == 0
            ? false
            : is_prime(n, n / 3, T{3});
}

但是改变一行(让布尔结果“非规范化”),它停止生成尾递归目标代码:

template<typename T>
constexpr bool is_prime(T number, T limit, T counter)
{
    return counter >= limit
        ? number % limit    // changed here
        : number % counter
            ? is_prime(number, number / counter, counter + 2)
            : false;
}

template<typename T>
constexpr bool is_prime(T n)
{
    return n == 2 || n == 3 || n == 5
        ? true
        : n <= 1 || n % 2 == 0
            ? false
            : is_prime(n, n / 3, T{3});
}

是铿锵声未能正确优化它还是有合理的原因?

要强制运行时评估,x是运行时积分素数≥ 13(一次递归)或足够大的 constexpr 素数,由于递归深度大,会阻止编译时评估:

is_prime(x);
4

1 回答 1

2

如果你有exp1 ? exp2 : exp3,要确定?:语句的类型,将类型exp3转换为类型exp2(如果可能)。这意味着您的漂亮bool结果被转换为类型T并且必须转换回 bool 才能返回。

这意味着递归调用不是最后一个语句。我相信如果你颠倒三元运算符中的顺序,你会得到尾递归结果。

template<typename T>
constexpr bool is_prime(T number, T limit, T counter)
{
    return counter < limit
        ? (number % counter
            ? is_prime(number, number / counter, counter + 2)
            : false)
        : number % limit;
}
于 2013-08-15T13:46:53.293 回答