chapter 13.pdf

函数模板

image.png
声明:不带大括号,可以多次声明
定义:带大括号,只能定义一次

  1. template<typename T> void fun(T); //声明,可用class代替typename
  2. template<typename T> void fun(T) //定义
  3. {
  4. }
  5. template<typename T> void fun(T input)
  6. {
  7. cout<<input<<endl;
  8. }
  9. template //表示模板函数
  10. T //模板形参,如果在编译期能够得到模板实参,则可在编译期实例化为实体函数
  11. input //函数形参,运行期调用

函数模板显示实例化

  1. fun<int>(3) //函数模板显式实例化,函数模板非函数不能调用,但是实例化后产生的函数为函数,可调用
  2. int //对应T,模板实参
  3. 3 //对应input,函数实参

编译期的两阶段处理
模板语法检查:
模板实例化:获取模板实参后,根据模板实参检查操作是否合法

模板必须在实例化的时候可见:整个程序可以多处定义,只要符合翻译单元处一处定义原则即可
与inline的区别:inline函数是在翻译单元中展开代码

类型推导

image.png

  1. template<typename T> void fun(T input) //定义
  2. {
  3. }
  4. int main()
  5. {
  6. fun(3); //隐式实例化,类型推导模板实参
  7. }

实例化控制

image.png

显式实例化定义

  1. //main.cpp
  2. #include "header.h"
  3. int main()
  4. {
  5. int x = 3;
  6. fun<int>(x);
  7. }
  1. //header.h
  2. #include<iostream>
  3. template<typename T>
  4. void fun(T x)
  5. {
  6. cout<<x<<endl;
  7. }
  8. //可以将定义与声明分开,只开放定义接口给用户
  9. template
  10. void fun<int>(int x); //显式实例化
  11. void fun(int x); //同上,显式实例化

显示实例化声明

避免多个相同实例化,提高编译连接速度

  1. //main.cpp
  2. #include <iostream>
  3. #include "header.h"
  4. extern template <typename T>//c++11,显式实例化声明
  5. void fun(int x);
  6. int main()
  7. {
  8. int x = 3;
  9. fun<int>(x);
  10. }
  1. //source.cpp
  2. #include "head.h"
  3. template
  4. void fun(int x)
  1. //header.h
  2. #include <iostream>
  3. template<typename T>
  4. void fun(T x)
  5. {
  6. cout<<x<<endl;
  7. }

模板形参推导

  1. //main.cpp
  2. #include <iostream>
  3. template <typename T>
  4. void fun(T x)
  5. {
  6. cout<< x <<endl;
  7. }
  8. template
  9. void fun(int* x); //实例化为第一个模板函数,
  10. template <typename T>
  11. void fun(T* x)
  12. {
  13. cout<< x <<endl;
  14. }
  15. template
  16. void fun(int* x); //实例化为第二个模板函数,形参推导为离当前实例化近的定义
  17. template
  18. void fun<int*>(int* x); //实例化为第一个模板函数,因为int*和参数列表的int*一致,T = int*
  19. int main()
  20. {
  21. }

函数模板的特化

  1. #include<iostream>
  2. template<typename T>
  3. void fun(T x)
  4. {
  5. cout<<x<<endl;
  6. }
  7. //可以将定义与声明分开,只开放定义接口给用户
  8. template
  9. void fun<int>(int x); //显式实例化
  10. void fun(int x); //同上,显式实例化
  11. //函数模板特化,为某些模板参数引入特殊的实现,下面带大括号,实例化无大括号
  12. template<> void fun<int>(int x)
  13. {
  14. }

类模板与成员函数模板

image.png

声明与定义

  1. template <typename T>
  2. class B
  3. {
  4. public:
  5. void fun(T input)//类内定义
  6. {
  7. cout<<input<<endl;
  8. }
  9. };//定义
  10. template <typename T>
  11. void B<T>::fun() //类外定义成员函数
  12. {
  13. }
  14. template<typename T>
  15. class B; //声明
  16. struct Str{};
  17. int main()
  18. {
  19. B<int>x; //实例化
  20. x.fun(3); //成员函数此时被实例化
  21. B<Str> y; //
  22. y.fun(Str{}) //错误:Str没有对应<<重载,但是上一句可以编译通过
  23. }

成员函数模板

1.普通的类包含成员模板

  1. class B
  2. {
  3. public:
  4. template <typename T>
  5. void fun(T input)//类内定义
  6. {
  7. cout<<input<<endl;
  8. }
  9. };//定义
  10. template <typename T>
  11. void B::fun() //类外定义成员函数,B后无尖括号
  12. {
  13. }

2.类模板的成员函数模板

  1. template <typename T>
  2. class B
  3. {
  4. public:
  5. template <typename T2>
  6. void fun(T2 input)//类内定义
  7. {
  8. 内部可以使用T,T2
  9. }
  10. };//定义
  11. template <typename T>
  12. template <typename T2>
  13. void B<T>::fun() //类外定义成员函数,两层template
  14. {
  15. }
  16. int main()
  17. {
  18. B<int>x;
  19. x.fun<float>(3.0);
  20. }

vector的实现:搜索gcc github vector

类模板实例化

image.png

  1. namespace N
  2. {
  3. template<typename T>
  4. class Y
  5. {
  6. void mf(){}
  7. };
  8. }
  9. using N::Y;
  10. template class N::Y<char*>; //实例化
  11. template void N::Y<double>::mf(); //只实例化成员函数

类模板特化:重要

  1. template<typename T>
  2. class B
  3. {
  4. void fun(){}
  5. };
  6. template<>
  7. class B<int> //特化版本
  8. {
  9. void fun(){}
  10. };

Concepts

模板相关内容