为什么下面的函数没有使用 Clang 生成尾递归?
Why the following function doesn't generate tail recursion with Clang?
在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});
}
是clang没有正确优化它还是有一个合理的原因?
为了强制运行时求值,x
是一个运行时整素数≥ 13
(一个递归)或一个足够大的constexpr素数,因为大的递归深度会阻止编译时求值:
is_prime(x);
如果您有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;
}
相关文章:
- 将公共递归转换为尾递归,因为大型输入的堆栈溢出
- 使用变量模板的递归计算 - gcc 与 clang
- 尾递归函数未被 g++ 优化
- 尾递归,带有通过引用传递的向量
- 如何使O(n)的函数检查字母(上和下)和()+-*/到尾递归?
- 基类 C++14 模板函数在 Mac OS 上的 clang 中不可见(递归模板)
- 是否有对 Clang 递归 ASTVisitor 的最终访问方法
- 带有对象的尾递归
- 无限递归模板实例化使用clang时GCC工作正常
- 在turbo c++中,可以将一个普通递归函数转换为尾递归函数来对其进行优化
- 为什么当递归函数结果相乘时,g++ 仍然优化尾递归
- 在 C++ 中使用尾递归函数计算列表的总和
- 叮当无限尾递归优化
- constexpr函数求值可以做尾递归优化吗?
- 尾递归函数,用于计算数组中大于平均值的所有数字
- 将递归函数转换为尾递归函数
- 为什么下面的函数没有使用 Clang 生成尾递归?
- 已知的最有效的尾递归素数验证函数是什么?
- 在c++中做尾递归
- 模板元编程的尾递归性能