我不明白这段代码(来自维基百科)是如何工作的:
template <int N>
struct Factorial
{
enum { value = N * Factorial<N - 1>::value };
};
template <>
struct Factorial<0>
{
enum { value = 1 };
};
// Factorial<4>::value == 24
// Factorial<0>::value == 1
void foo()
{
int x = Factorial<4>::value; // == 24
int y = Factorial<0>::value; // == 1
}
<int N>
的奇怪模板是什么?<>
是什么?enum
是用来做什么的?谢谢!
发布于 2010-06-20 20:51:39
<int N>
的奇怪模板是什么?在C++中,模板参数可以是类型(以class
或typename
作为前缀),也可以是整数(以int
或unsigned int
为前缀)。这是第二种情况。
template <>
是什么?template<> struct Factorial<0>
是阶乘类模板的一个完全专门化,这意味着0
被认为是一个特殊值,它对应于它自己版本的阶乘。
枚举是计算元编程C++中值的方法。
首先,创建这段代码的原因是为了证明微积分可以使用元编程来完成。其优点是生成的代码非常高效(调用Factorial<4>::value
相当于在代码中编写"24“。
这种方法很少实现这样的功能,但是现在元编程的使用越来越多。请参阅Boost元编程库以获得可以完成的操作的提示。
发布于 2010-06-21 03:23:57
采用
<int N>
的这个奇怪的模板是什么?
可以对类/类型、值和指针进行模板声明。您通常不会将此表单视为定义模板,很少在模板参数中使用常量。
第二个奇怪的模板<>是什么?
考虑模板的最佳方法是做一些类似于编译器所做的事情:将模板看作一个类,在该类中用该类型的实际值替换模板参数。
这是指:
template <int N>
struct Factorial
{
enum { value = N * Factorial<N - 1>::value };
};
Factorial<2>::value
相当于:
// generated by the compiler when Factorial<2>::value is encountered in code:
struct Factorial2 { enum { value = 2 * Factorial1::value }; };
struct Factorial1 { enum { value = 1 * Factorial0::value }; };
// not generated by compiler, as it was explicitly defined in the code you ask about:
template <> struct Factorial<0> { enum { value = 1 }; }; // defines Factorial<0>
这些帐篷是做什么用的?
它们在编译时使用const value
定义枚举,允许您编写类似示例中的客户端代码。
与一般的运行时阶乘计算相比,使用这种方法有什么好处呢?
其优点是效率高。由于值计算是在编译时扩展的,因此Factorial<10>::value
的运行时成本与Factorial<1>::value相同。在编译的代码中,它们都是常量。如果要在性能关键代码中计算阶乘,并且在编译时知道它是哪个值,则应该这样做,或者脱机计算它,并在代码中定义一个带有预先计算值的常量。
你们多久用一次这个?
您指的是常数的递归计算吗?如果是这样的话,就不会经常。
这是模板中常量的定义吗?经常:)
“此”是特定类型模板的细化吗?很多时候。我理解在一些STL实现中,std::vector有一个完全独立的实现(一个具有8个元素的std::vector<bool>
不需要超过一个字节来存储这些值)。
我使用C++已经有一段时间了,但以前从未使用过。我错过了C++有多大一部分?
不一定是个大角色。如果您使用boost,您使用的代码很可能是使用这样的方式实现的。
发布于 2010-06-21 06:26:59
我把答案贴在这里,假设约翰对此没意见。如果他不喜欢的话,我就把它去掉
是的,它是一个非类型的参数.可以有几种模板参数。
你拥有的是最后一种。它是一个编译时间常数(所谓的常量表达式),是整数或枚举的类型。在标准中查找它之后,我不得不将类模板移到类型部分--尽管模板不是类型。但它们被称为类型参数,目的是为了描述这些类型。您可以拥有指针(也可以是成员指针)和对具有外部链接的对象/函数的引用(这些对象/函数可以从其他对象文件链接,并且其地址在整个程序中是唯一的)。示例:
模板类型参数:
template<typename T>
struct Container {
T t;
};
// pass type "long" as argument.
Container<long> test;
模板整数参数:
template<unsigned int S>
struct Vector {
unsigned char bytes[S];
};
// pass 3 as argument.
Vector<3> test;
模板指针参数(将指针传递给函数)
template<void (*F)()>
struct FunctionWrapper {
static void call_it() { F(); }
};
// pass address of function do_it as argument.
void do_it() { }
FunctionWrapper<&do_it> test;
模板引用参数(传递整数)
template<int &A>
struct SillyExample {
static void do_it() { A = 10; }
};
// pass flag as argument
int flag;
SillyExample<flag> test;
模板参数
template<template<typename T> class AllocatePolicy>
struct Pool {
void allocate(size_t n) {
int *p = AllocatePolicy<int>::allocate(n);
}
};
// pass the template "allocator" as argument.
template<typename T>
struct allocator { static T * allocate(size_t n) { return 0; } };
Pool<allocator> test;
没有任何参数的模板是不可能的。但是没有任何显式参数的模板是可能的-它有默认参数:
template<unsigned int SIZE = 3>
struct Vector {
unsigned char buffer[SIZE];
};
Vector<> test;
从语法上讲,template<>
保留用于标记显式模板专门化,而不是没有参数的模板:
template<>
struct Vector<3> {
// alternative definition for SIZE == 3
};
https://stackoverflow.com/questions/3082113
复制