我用了一个例子
http://en.wikipedia.org/wiki/Template_metaprogramming
const unsigned long long y = Factorial<0>::value; // == 1
我知道编译器可以进行类型检查,但我认为您不能将 0 放在类型应为的位置,并将其作为值。
有人可以解释这是如何工作的吗?
谢谢
我用了一个例子
http://en.wikipedia.org/wiki/Template_metaprogramming
const unsigned long long y = Factorial<0>::value; // == 1
我知道编译器可以进行类型检查,但我认为您不能将 0 放在类型应为的位置,并将其作为值。
有人可以解释这是如何工作的吗?
谢谢
我不认为你可以把 0 放在类型应该是的地方,它会被当作值
问题在于假设:它不是“类型应该在哪里”。相反,它是“可以指定模板参数的地方”。
在这种情况下,有一个非类型模板参数。
它之所以有效,仅仅是因为它是一个不同于type template arguments的特性。
就是这样。我可以推荐C++ Templates: the Complete Guide或该列表中的许多其他书籍来阅读 C++ 模板的基础知识。
在那个特定的例子中:
template <int N>
struct Factorial {
enum { value = N * Factorial<N - 1>::value };
};
template <>
struct Factorial<0> {
enum { value = 1 };
};
编译器递归地生成类。请记住,模板本身不是一个类,只是生成类的一组规则。
最初,仅Factorial<0>
存在。然后你写:
const int x = Factorial<4>::value;
这告诉它它需要生成Factorial<4>
将转换为的类:
template <>
struct Factorial<4> {
enum { value = 4 * Factorial<3>::value };
};
这再次告诉它生成类Factorial<3>
等等。当它到达时停止,Factorial<0>
因为它已经定义并且不需要生成新的类来计算它的value
成员。
基本上,它将计算从运行时转移到编译时。请注意,这并不总是有效(取决于 的值N
,您的编译器可能不支持那么多级别的模板递归)。此外,这会增加代码大小。
这是为了如何 - 为什么这样做是因为它是标准允许的。