模板规范
template 声明指定参数化类或函数的集。
template < template-parameter-list > declaration
备注
“模板参数列表” 是模板参数的逗号分隔的列表,它可能是在窗体“类”、“标识符”、“类型名称” “标示符” 或 模板<”模板参数列表“>类“标示符” 中的类型或在模板主体中使用的非类型参数。 模板参数的语法是以下的其中一个:
parameter-declaration
class identifier [ = typename ]
typename identifier [ = typename ]
template < template-parameter-list > class [identifier][= name]
您必须实例化类模板,就像您要实例化普通类一样,但是在尖括号 (<>) 内必须包括模板参数。 这些模板参数可以是任何类型,如果模板参数列表包含类或“类名称”关键字,如果该参数是非类型参数则为合适类型的值。 不需要特殊语法调用函数模板,尽管,可能需要尖括号和模板参数,如果模板参数不能从参数推导到函数。
“模板参数列表” 是指定紧跟其后的代码哪一个部分将改变的模板函数所使用的参数列表。 例如:
template< class T, int i > class MyStack...
在这种情况下,该模板可以接到类型 (class T) 和常量参数 (int i)。 在实例化时,模板将使用类型 T 和常量整数 i。 在 MyStack 声明体内,您必须引用 T 标识符。
模板声明本身不生成代码;它指定类或函数的系列以及当被其他代码引用时生成的一个或多个代码。
模板声明有全局、命名空间或类范围。 它们不能在函数内声明。
以下示例阐释具有类型参数 T 和非类型模板参数 i 的类模板的声明、定义和实例化。
// template_specifications1.cpp
template <class T, int i> class TestClass
{
public:
char buffer[i];
T testFunc(T* p1 );
};
template <class T, int i>
T TestClass<T,i>::testFunc(T* p1)
{
return *(p1++)
};
// To create an instance of TestClass
TestClass<char, 5> ClassInst;
int main()
{
}
非类型模板参数
非类型模板参数必须是整型、枚举、指针、引用或指向成员类型的指针,并且必须是在编译时的常量。 它们可以被限定为常数或可变类型。 浮点值不允许作为模板参数。 类、结构或联合类型的对象不允许作为非类型模板参数,尽管指向此类对象的指针是被允许的。 作为非类型模板参数传递的数组转换为指针。 作为非类型参数传递的函数被视为函数指针。 字符串文本不允许作为模板参数。
在模板声明中使用类型名称
这些typename 关键字可用于模板参数列表之中。 以下模板声明是相同的:
template< class T1, class T2 > class X...
template< typename T1, typename T2 > class X...
用于模板参数的默认参数
类模板可以使用后跟默认类型或值的 = 符号来指定默认参数。 函数模板不能具有默认参数。 有关更多信息,请参见 类模板的默认参数。:
template<typename Type> class allocator {};
template<typename Type,
typename Allocator = allocator<Type> > class stack
{
};
stack<int> MyStack;
重用模板参数
模板参数可以重用于模板参数列表中。 例如,下面的代码是允许的的:
// template_specifications2.cpp
class Y
{
};
template<class T, T* pT> class X1
{
};
template<class T1, class T2 = T1> class X2
{
};
Y aY;
X1<Y, &aY> x1;
X2<int> x2;
int main()
{
}
用作模板参数的模板
模板参数本身可以是模板。 此构造意味着该参数必须本身是模板,而不是由模板构造的类。 在下面的示例中,模板 template 参数的模板参数的名称 A 可以省略,因为没有方式可以使用它。
// template_specifications3.cpp
#include <stdio.h>
template <class T> struct str1
{
T t;
};
template <template<class A> class T> struct str2
{
T<int> t;
};
int main()
{
str2<str1> mystr2;
mystr2.t.t = 5;
printf_s("%d\n", mystr2.t.t);
}
Output
5
用作模板参数的引用
visual studio .NET 2003 引入了使用引用作为非类型模板参数的功能。 这在先前的版本中是不允许的。
// references__supported_as_nontype_template_parameters.cpp
#include <stdio.h>
extern "C" int printf_s(const char*,...);
template <int & ri> struct S
{
S()
{
printf_s("ri is %d\n", ri);
}
~S()
{
printf_s("ri is %d\n", ri);
}
};
int i = 1;
int main()
{
S<i> s;
i = 0;
}
Output
ri is 1
ri is 0
嵌套模板实例
嵌套模版实例声明时,Visual Studio 2005 要求先于 Versions of Visual Studio 插入空白模版参数列表。 以下语法现在允许:
// template_specifications4.cpp
template <typename T>
class A
{
};
template <int n>
class B
{
};
int main()
{
A<B<22>>();
}