模板<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; } 

当然,模板版本十亿倍更安全,更灵活。