模板<unsigned int N>是什么意思?
当声明一个模板时,我习惯了这样的代码:
template <class T>
但在这个问题上 ,他们用了:
template <unsigned int N>
我检查了它编译。 但这是什么意思? 它是一个非types的参数? 如果是这样,我们怎么能有一个没有任何types参数的模板?
在一个整数而不是一个types上模拟一个类是完全可能的。 我们可以将模板值赋给一个variables,或者以其他任何整数字面值的方式对其进行操作:
unsigned int x = N;
事实上,我们可以创build在编译时(从维基百科 )评估的algorithm:
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 }
是的,这是一个非types的参数。 你可以有几种模板参数
- types参数。
- types
- 模板(只有类和别名模板,没有函数或variables模板)
- 非types参数
- 指针
- 参考
- 积分常量expression式
你有什么是最后一种。 这是一个编译时间常量(所谓的常量expression式),是整型或枚举types的。 在标准中查找之后,我不得不将类模板移动到types部分 – 即使模板不是types。 但是为了描述这些types,它们被称为types参数。 你可以使用指针(也是成员指针)和引用具有外部链接的对象/函数(可以链接到其他对象文件,并且在整个程序中地址是唯一的)。 例子:
模板types参数:
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 };
你根据'unsigned int'为你的课程模板化。
例:
template <unsigned int N> class MyArray { public: private: double data[N]; // Use N as the size of the array }; int main() { MyArray<2> a1; MyArray<2> a2; MyArray<4> b1; a1 = a2; // OK The arrays are the same size. a1 = b1; // FAIL because the size of the array is part of the // template and thus the type, a1 and b1 are different types. // Thus this is a COMPILE time failure. }
一个模板类就像一个macros,只是less了一大堆邪恶。
把模板想象成一个macros。 当您使用模板定义类(或函数)时,将模板的参数replace为类(或函数)定义。
不同之处在于参数具有“types”,并在编译期间检查传递的值,如函数的参数。 有效的types是您的常规C ++types,如int和char。 当你实例化一个模板类时,你传递了你指定的types的值,并且在模板类定义的一个新副本中,这个值在参数名称在原始定义中的任何地方被replace。 就像一个macros。
你也可以使用“ class
”或“ typename
”types的参数(他们真的是一样的)。 使用这些types之一的参数,您可以传递types名称而不是值。 就像以前一样,只要你创build一个新的实例,参数名称在模板类定义中就变成了你传递的任何types。 这是模板类最常用的用法; 每个知道C ++模板的人都知道如何做到这一点。
考虑这个模板类示例代码:
#include <cstdio> template <int I> class foo { void print() { printf("%i", I); } }; int main() { foo<26> f; f.print(); return 0; }
它在function上与这个使用macros的代码相同:
#include <cstdio> #define MAKE_A_FOO(I) class foo_##I \ { \ void print() \ { \ printf("%i", I); \ } \ }; MAKE_A_FOO(26) int main() { foo_26 f; f.print(); return 0; }
当然,模板版本十亿倍更安全,更灵活。