持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第11天,点击查看活动详情。 写文章不易,阅读之前请给我点个赞吧~
憋了我两天的一段 C++ 模板代码,要补补泛型编程和模板了,看到了下面的 const T(&x)[Dim] 我懵了一下,这究竟是什么东西!下面我们一起来看一下吧~
template<class T, int Dim>
bool WriteItem(Json& cJson, const T(&x)[Dim])
{
for (int i = 0; i < Dim; ++i)
{
if (!WriteItem(cJson[i], x[i]))
{
return false;
}
}
return true;
}
模板基础
模板以关键字 template 开头,后接模板形参表,模板形参表是用尖括号括住的一个或多个模板形参的列表,形参之间以逗号分隔,模板形参表不能为空:
template <class T, size_t N>
模板形参表示可以在类或函数的定义中使用的类型或值。模板形参可以是表示类型的类型形参,也可以是表示常量表达式的非类型形参。类型形参跟在关键字 class 或 typename 之后定义,这里 class 和 typename 没有区别。非类型形参跟在类型说明符之后声明。
这里的 N 就是非类型形参,是一个固定类型的常量而不是一个类型,还可以是 int double等等。
调用函数模板时,编译器将确定用什么类型代替每个类型形参,以及用什么值代替每个非类型形参。推导出实际模板实参后,编译器使用实参代替相应的模板形参产生编译该版本的函数。编译器承担了为我们使用的每种类型而编写函数的单调工作。
与调用函数模板形成对比,使用类模板时,必须为模板形参显式指定实参: list ls; 这是一种什么样的功法呢?
在调用函数时非类型形参将用值代替,值的类型在模板形参表中指定。例如,下面的函数模板声明了 array_init 是一个含有一个类型模板形参和一个非类型模板形参的函数模板:
template <class T, size_t N>
void array_init(T (&parm)[N])
{
for(size_t i = 0; i != N; ++i)
{
parm[i] = 0;
}
}
当调用 array_init 时,编译器从数组实参计算非类型形参的值:
int x[42];
double y[10];
array_init(x); //等价于 实例化 array_init(int(&)[42])
array_init(y); //等价于 实例化 array_init(double(&)[10]
如果上述函数是类的成员函数,以及在测试的时候应该注意什么呢?这里有两种情况,也就是这个函数是非静态成员函数或是静态成员函数,他们的调用情况如下所示。
类名::静态成员函数(); // 这个是对的
类名::非静态成员函数(); // 这个是错的,会提示非静态成员函数的非法调用
类名 对象;
对象.静态成员函数(); // ok
对象.非静态成员函数(); // ok
所以最上面的函数应该如何调用呢?应该已经十分清晰了吧~