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

模板定义

模板编译

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

类模板作用于声明类

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

模板类型的别名

template<typename T> using twin = pair<T, unsigned>;
twin<string> books; // books是pair<string, unsigned>
twin<int> booksNo; // booksNo是pair<int, unsigned>

显式实例化

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

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

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

模板类型转换

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

template <typename T> T fobj(T, T);
template <typename T> 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 <typename T> rep (const T &t);
template <typename T> rep (T *t);

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

扩展包写法理解

template <typename... Args> 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))
}
posted @ 2022-01-17 00:45  二律背反GG  阅读(200)  评论(0编辑  收藏  举报