1,非类型模板形参
模板的形参并不一定都代表未定的类型,也可以是一个实实在在的值,这样的模板形参称之为非类型形参。
需要注意的是,这个值必须是常量值。
需要进一步说明的是,常量表达式的定义是:编译器在编译时就能计算出结果的整型表达式。
所以,非类型形参必须是整型常量。
举一个简单而无用的例子:
<pre name="code" class="cpp">
int main()
{
NoUse<3132> NoUse_1;
cout << NoUse_1.width << endl;
system("pause");
return 0;
}
system("pause");return 0;}
执行结果:
3132
例子中的w即为非类型形参,其类型必须是固定的。
w的值不能被修改,且只能在模板的定义体中使用,w不是成员。。
如果将代码修改如下:
template<int w> class NoUse
{
public:
NoUse() :width(w){}
int width;
};
int main()
{
NoUse<3132> NoUse_1;
cout << NoUse_1.width << endl;
<pre name="code" class="cpp">template<int w> class NoUse
{
public:
NoUse() :width(w) {w = 3}
int width;
};
则编译报错:
error C2106: “=”: 左操作数必须为左值
因为w是常量。
2,非模板形参必须是整型吗?
将第一个例子的代码修改为如下形式
template<double w> class NoUse
{
public:
NoUse() :width(w) {}
double width;
};
int main()
{
NoUse<31.32> NoUse_1;
cout << NoUse_1.width << endl;
system("pause");
return 0;
}
我们看到,两处代码唯一的改变就是讲非类型形参和数据成员由int变成了double。
编译,报错:
error C2993: “double”: 非类型模板参数“w”的类型非法
可见,非类型形参确实只能是整型。
3,非类型形参与数组长度
首先,数组引用的写法是:
int (&array)[5]
将数组用作函数的输入参数,可以用模板来灵活实现:
template <class T, size_t N> void array_init(T(&parm)[N])
{
for (size_t i = 0; i != N; i++)
{
parm[i] = i;
}
}
或者实现一个简单的返回数组长度的模板函数:
template <class T, size_t N> size_t get_array_len(T(&parm)[N])
{
return N;
}
int main()
{
double arr[10];
cout << get_array_len(arr) << endl;//用数组arr实例化函数模板,数组长度N自动获得,虽然不明白其原理
system("pause");
return 0;
}
执行,结果:
10
在C语言下很难实现的获得数组长度的功能,在C++下轻松实现了。
4,编写泛型代码的两个原则
- 模板的形参是const引用;
- 函数体中的测试,只用“<”比较