c++学习笔记(六)—— 模板定义


模板定义

模板编译

编辑器遇到一个模板定于时,不会生成代码,而是在使用的时候生成代码。
所以在声明的时候,就需要知道定义。即函数模板和类模板的成员函数的定义通常放在头文件中。

类模板作用于声明类

在一个类模板的作用于内,我们可以直接使用模板名而不必指定模板实参。

模板类型的别名

template using twin = pair;
twin books; // books是pair
twin booksNo; // booksNo是pair

显式实例化

目的是为了避免在多个文件中实例化相同模板,导致额外开销严重的问题

extern template declaration;  //声明
template declaration;   //定义
extern template class Blob;
template int compare(const int& a, const int& b); 

note

  1. 当我们希望通知编辑器一个名字表示类型时,必须使用关键字typename,而不能使用class
  2. 成员模板不能是虚函数

模板类型转换

将实参传递给带模板类型的函数形参时,能够自动应用的类型转换只有const转换及数组或函数到指针的转换

template  T fobj(T, T);
template  T fref(const T&, const T&);

int a[10], b[42];
fobj(a, b); // fobj(int* ,int *)
fref(a, b); // 错误:数组类型不匹配

模板重载中,匹配的优先级

如果一个模板直接匹配,而另一个模板要类型转换才能匹配,则优先前者。

如果匹配的重载是提供同样好的匹配的话,按照以下规则判断

  1. 非模板函数和模板函数,优先前者
  2. 多个重载模板对一个调用提供同样好的匹配时,应选择最特例化的版本
  3. 如果都不满足,则此调用有歧义

规则2样例:

template  rep (const T &t);
template  rep (T *t);

string s("1");
const string* sp = &s;
rep(sp);
// 这里会调用第二个
// 【const T &t】本质上可以用于所有类型,【T *t】只能用于指针
// 所以第二个更特例化

扩展包写法理解

template  rep (const Args&... rest)
{
    print(debug_rep(rest)...);
    //如果调用 rep(1, 2, 3, 4);
    //等价于 print(debug_rep(1), debug_rep(2), debug_rep(3), debug_rep(4))

    print(debug_rep(rest...));
     //如果调用 rep(1, 2, 3, 4);
    //等价于 print(debug_rep(1, 2, 3, 4))
}