我有一些模板化代码,编译器可以对大多数数据类型进行尾部调用优化,但不能对其他数据类型进行尾部调用优化。代码实现了pow()
template<typename T, typename U>
void powRecurse(T& x, U& y, T& acc)
{
if(y == 0) {
acc = Identity<T>;
return;
}
if(y == 1) {
acc = acc * x;
return;
}
if(y % 2 == 1) {
acc = acc * x;
y = y - 1;
}
x = x*x;
y = y/2;
powRecurse<T, U>(x, y, acc);
}
template<typename T, typename U>
T tailPow(T x, U y)
{
T rv = Identity<T>;
powRecurse<T, U>(x, y, rv);
return rv;
}
参数 T 的类型似乎对尾部调用优化没有影响,我尝试过的任何类型都可以使用参数 U 的正确类型进行尾部调用优化。如果参数 U 是 uint64_t ,则编译器可以尾部调用优化。如果它是 boost::multi precision::cpp_int 那么编译器不会尾部调用优化。
我还尝试将 uint64_t 包装在一个类中,并在 int 类型上包装一个模板包装器,这两个尾部调用都进行了优化。
有什么理由不应该尾部调用优化吗?显然我可以循环这个,但我真的只是想理解这里的语言或编译器问题。
惰性求值意味着所有“递归”函数调用实际上都是不同的函数模板实例化。
参见例如这里有类似的讨论:
- Boost 多精度:递归模板实例化超出最大长度 256
- or here 如何将 sqrt 和 ceil 与 Boost::multi precision 一起使用?
因此,您可以通过选择退出惰性求值模板表达式来获得您期望的所有 tail-coll 实现细节(boost::multiprecision::et_off
如链接中所述),但请务必检查减少的代码大小和感知的 TCO 优化actually导致性能提高。
实际上,某些算法受益于表达式模板,这些模板可以跳过常见的子表达式、重新排序无损操作等。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)