3

我找到了以下代码,它似乎可以工作,但我根本无法理解。
它看起来像一个递归结构,但我以前从未见过。

template<int B, int N>
struct Pow {
    enum{ value = B*Pow<B, N-1>::value };
};

template< int B >
struct Pow<B, 0> {
    enum{ value = 1 };
};
int quartic_of_three = Pow<3, 4>::value;

知道这是什么吗?

4

2 回答 2

3

这是一种在编译时计算积分幂的方法,依赖于支持必要数量的模板特化的编译器(即,它不是完全可移植的代码)

阅读您最喜欢的 C++ 教科书中的模板

如果您还没有 C++ 教科书:您需要它,请查看 SO FAQ C++ 书籍列表


在 C++11 中,一种更好且(几年后)可能更便携的方法是使用一个constexpr函数:

#include <iostream>
using namespace std;

constexpr int constpow( int base, int n )
{
    return (n == 0? 1 : base*constpow( base, n - 1 ));
}

int main()
{
    int const quarticOfThree = constpow( 3, 4 );
    wcout << quarticOfThree << endl;
}

但是,Visual C++ 11.0 不支持这一点,我写这篇文章时是 Visual C++ 的最新版本

于 2013-01-04T03:17:09.653 回答
2

此模板定义中需要注意的重要事项是:

  • 模板参数是values,而不是人们通常在模板中期望的类型;
  • struct 模板的字段value是根据这些参数计算的;
  • N当使用 设置时,模板对第二个参数有部分特化0

正如您所注意到的,模板在value字段计算上递归。如果未定义部分特化,则该递归将是无限的。当第二个参数“到达”0时,即。当通过遵循模板实例化的嵌套以尝试获取计算最外层所需的连续值字段时,编译器最终需要实例化具有参数 N 等于 的模板0,并选择包含常量的偏特化版本字段的值1。然后编译器可以计算每个嵌套值字段,最终返回到最外层。

使用这种技术,可以让编译器离线计算某些值(即在编译时)。这让程序员可以通过参数和公式定义常量值,而不必对它们进行硬编码,或者让编译后的程序在每次运行时计算它们。

但是这种方法的问题,它看起来多么聪明,是它的可读性,因此易于维护。这很可能是新标准提供constexpr概念的原因,这是定义所谓的纯计算的一种非常合适的方法。


应该注意的是,模板的两个字段都已签名,并且计算不会尝试以任何方式处理负值。如果 N 最初设置为-1,结果可能很有趣。

于 2013-01-04T04:02:31.260 回答