【语法】模板

来源:互联网 发布:资历章排列软件 编辑:程序博客网 时间:2024/05/12 13:22
  • 泛型代码两个原则:

    1 模板中函数参数是const的引用:保证函数可用于不能拷贝的类型
    2 函数体只是用<比较运算


  • 类型模板参数:
template<typename T> inline bool compare(const T& lhs, const T& rhs){    return lhs < rhs;}

  • 非类型模板参数:
template<unsigned N> inline int back(const int (&lhs)[N]){    return lhs[N - 1];}int main(){    const int a[2]{1, 2};    cout<<back(a);    return 0;}

1 数组作为非引用参数会被退化为指针,无法推导出N,需要使用引用保持数组类型

注意区别引用的数组

bool back(int &lhs[2])//非法

数组的引用

bool back(int (&lhs)[2])

2 inline说明符放在模板参数列表之后


  • 模板编译:

编译器遇到模板定义时,并不生成代码。只有当实例化出模板的特定版本时,编译器才会生成代码,为了生成一个实例化版本,编译器需要掌握函数模板或类模板的成员函数的定义。因此,模板的头文件包含声明和定义。函数模板和类模板的成员函数定义放在头文件中。


  • 类模板

函数模板可以推导参数类型,类模板不可以,需要额外提供信息

template<typename T> class Blob{private:    vector<T> vec;public:    void func(const T& lhs);};template<typename T> void Blob<T>::func(const T& lhs){    vec.push_back(lhs);}int main(){    Blob<int> b;    b.func(2);    return 0;}

使用类模板类型时必须提供模板参数,
在类模板自己的作用域中,可以直接使用模板名而不提供实参,
在类外定义成员时,直到遇到类名::才算进入类作用域

template<typename T>Blob<T> Blob<T>::operator++(int lhs){    Blob ret = *this;    return ret;}

  • 使用类的类型成员

默认情况下,作用域运算符访问的是名字,不是类型。使用typename显示告诉编译器访问的是类型。

template <typename T>typename T::value_type top(const T& c){    return typename T::value_type();}

  • 模板成员函数:

模板成员函数不能是虚函数

template<typename T>template<typename It>Blob <T>::Blob(It b, It e){    vec.insert(vec.begin(), b, e);}

类模板外定义成员模板函数时,必须同时为类和成员模板提供模板参数列表,编译器根据实参推断模板成员函数的参数类型。


  • 控制实例化

当两个或者多个独立编译的源文件使用了相同的模板,并提供了相同的模板参数,每个文件都会有改模板的一个实例。
通过显示的实例化避免开销

A文件:

extern template class Blob<string>; //实例化声明Blob<string> s1;//实例化在其他文件

B文件:

template class Blob<sting>;//实例化定义

将一个实例化声明为extern就表示承诺在程序的其他位置有该实例化的非extern声明(定义)。

与普通实例化不同,实例化定义会实例化所有成员
普通情况下,类模板的成员函数只有当程序用到它时才会实例化。


  • 函数模板显式实参
template<typename T1,typename T2,typename T3>T1 sum(T2, T3);auto func = sum<long>(i,j)

特别是当返回类型与函数参数列表中的所有类型不一致时,需要显式指出返回类型。

为了不显式实参,可以使用尾置返回类型

template<typename It>auto func(It begin, It end)->decltype(*begin){    return *begin;}

解引用返回左值,decltype推断的类型为begin所指元素类型的引用

若只要返回值,不返回引用,可使用类型转换模板进行类型转换


原创粉丝点击