为什么使用boost :: multiprecision :: cpp_int会影响尾调用优化

时间:2017-02-07 01:26:15

标签: c++ optimization boost

我有一些模板化的代码,编译器可以为大多数数据类型而不是其他数据类型进行尾调用优化。该代码实现了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 :: multiprecision :: cpp_int那么编译器不会尾调用optimize。

我还尝试在一个类中包装一个uint64_t,在一个int类型上包装一个模板包装器,它们都尾调用optimize。

有什么理由不应该尾调用优化?显然我可以循环这个,但我真的只是想在这里理解语言或编译器问题。

1 个答案:

答案 0 :(得分:1)

懒惰评估意味着所有&#34;递归&#34;函数调用实际上是不同的函数模板实例化。

参见例如这里有类似的讨论:

因此,您可以通过选择退出惰性评估模板表达式(boost::multiprecision::et_off,如链接中所述)来获得所有tail-coll实现细节,但请务必检查是否已减少代码大小和感知的TCO优化实际会提高性能。

实际上,某些算法可以从表达式模板中受益,这些模板可以跳过常见的子表达式,重新排序无损操作等。