• C++:array,模板特化 详解


     

    目录

    一.容器array

    1.介绍

    2.array和vector比较

     3.array和原生数组比较——array唯一优势:有越界检查

     4.总结建议:用vector别用array

    5.非类型模板参数

    (1)非类型模板参数是常量,不可修改

     (2)非类型模板参数一般就是整形。

    二.模板的特化

    1.函数模板特化

    2.类模板特化

    1.介绍

    2.示例2:仿函数的偏特化使用


    一.容器array

    1.介绍

     固定长度的顺序容器,就是定长数组

    2.array和vector比较

    vector是动态开辟的,放在堆上的,且内部存的是指针;array就是个定长数组,放在栈上的,内部存的就是个数组

     3.array和原生数组比较——array唯一优势:有越界检查

    array相比原生数组唯一优势:有越界检查,因为有[]运算符重载,[]运算符重载中有assert检查。

     4.总结建议:用vector别用array

    array对比原生数组,还是有一些越界检查的优势的。但是实际中我们统一直接用vector更香!

    5.非类型模板参数

    (1)非类型模板参数是常量,不可修改

     (2)非类型模板参数一般就是整形。

    整形int,char,unsigned int等。
    1.浮点数、类对象以及字符串是不允许作为非类型模板参数的。
    2.非类型的模板参数必须在编译期就能确认结果。

    二.模板的特化

    1.函数模板特化

    函数模板的特化步骤:
    1. 必须要先有一个基础的函数模板
    2. 关键字 template 后面接一对空的尖括号 <>
    3. 函数名后跟一对尖括号,尖括号中指定需要特化的类型
    4. 函数形参表 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误。
    1. template<class T>
    2. bool Less(T left, T right) //模板函数
    3. {
    4. return left < right;
    5. }
    6. 针对某些类型要特殊化处理
    7. template<>
    8. bool Less(Date* left, Date* right) //模板特化
    9. {
    10. return *left < *right;
    11. }
    12. bool Less(Date* left, Date* right) //原生函数
    13. {
    14. return *left < *right;
    15. }
    16. 函数模板基本不用特化方式处理,直接写一个具体类型的函数更好、
    17. int main()
    18. {
    19. cout << Less(1, 2) << endl; // 可以比较,结果正确
    20. Date d1(2022, 7, 7);
    21. Date d2(2022, 7, 8);
    22. cout << Less(d1, d2) << endl; // 可以比较,结果正确
    23. Date* p1 = new Date(2022, 7, 16);
    24. Date* p2 = new Date(2022, 7, 15);
    25. cout << Less(p1, p2) << endl; // 可以比较,结果正确 3.
    26. return 0;
    27. }

    正常的Less(d1, d2)比较日期类大小, 传进left < right后按照Date中的<运算符重载进行比较,但是Less(p1, p2)传的是指针,如果用模板函数会比较指针,所以这里用到模板特化函数去设置形参是Date*时比较*left < *right,类似于上面这种,就叫模板特化。当然也可以直接写出原生的函数,在没有原生函数的条件下,第3个Less(p1, p2)会优先调用模板特化函数,有原生函数会优先调用原生函数,在函数模板中是可以并存的,类模板中这样没法用。所以结论是:函数模板没必要特化,直接用原生函数就行

    2.类模板特化

    1.介绍

    全特化即是将模板参数列表中所有的参数都确定化
     半特化/偏特化 :
    1、将模板参数类表中的一部分参数特化。
    2、偏特化并不仅仅是指特化部分参数,而是针对模板参数更进一步的条件限制所设计出来
    1. template<class T1, class T2>
    2. class Data
    3. {
    4. public:
    5. Data() { cout << "Data" << endl; }
    6. private:
    7. T1 _d1;
    8. T2 _d2;
    9. };
    10. // 全特化 :全特化即是将模板参数列表中所有的参数都确定化
    11. template<>
    12. class Data<int, double>
    13. {
    14. public:
    15. Data() { cout << "Data" << endl; }
    16. };
    17. // 半特化/偏特化 1:
    18. // 1、将模板参数类表中的一部分参数特化。
    19. template<class T1>
    20. class Datachar>
    21. {
    22. public:
    23. Data() { cout << "Data" << endl; }
    24. };
    25. // 半特化的写法2:
    26. // 2、偏特化并不仅仅是指特化部分参数,而是针对模板参数更进一步的条件限制所设计出来
    27. //的一个特化版本。
    28. template<class T1, class T2>
    29. class Data
    30. {
    31. public:
    32. Data() { cout << "Data" << endl; }
    33. };
    34. // 半特化的写法3:
    35. template<class T1, class T2>
    36. class Data
    37. {
    38. public:
    39. Data() { cout << "Data" << endl; }
    40. };
    41. int main()
    42. {
    43. Data<int, int> d1;
    44. Data<int, double> d2;
    45. Data<int, char> d3;
    46. Data<char, char> d4;
    47. Data<int*, int*> d5;
    48. Data<int*, char*> d6;
    49. Data<int*, string*> d7;
    50. Data<int*, void*> d8;
    51. Data<int*, int> d9;
    52. Data<int&, char&> d10;
    53. return 0;
    54. }

    2.示例2:仿函数的偏特化使用

    1. #include
    2. #include
    3. template<class T>
    4. struct Less //模板函数
    5. {
    6. bool operator()(const T& x, const T& y) const
    7. {
    8. return x < y;
    9. }
    10. };
    11. //template<> 这样写只能传Date*,所以不如干脆写个偏特化可以传任何指针类型
    12. //struct Less
    13. //{
    14. // bool operator()(Date* x, Date* y) const
    15. // {
    16. // return *x < *y;
    17. // }
    18. //};
    19. // 偏特化
    20. template<class T> //模板偏特化函数
    21. struct Less
    22. {
    23. bool operator()(T* x, T* y) const
    24. {
    25. return *x < *y;
    26. }
    27. };
    28. int main()
    29. {
    30. Date d1(2022, 7, 7);
    31. Date d2(2022, 7, 6);
    32. Date d3(2022, 7, 8);
    33. vector v1;
    34. v1.push_back(d1);
    35. v1.push_back(d2);
    36. v1.push_back(d3);
    37. // 可以直接排序,结果是日期升序
    38. sort(v1.begin(), v1.end(), Less());
    39. vector v2;
    40. v2.push_back(&d1);
    41. v2.push_back(&d2);
    42. v2.push_back(&d3);
    43. // 可以直接排序,结果错误日期还不是升序,而v2中放的地址是升序
    44. // 此处需要在排序过程中,让sort比较v2中存放地址指向的日期对象
    45. // 但是走Less模板,sort在排序时实际比较的是v2中指针的地址,因此无法达到预期
    46. sort(v2.begin(), v2.end(), Less());
    47. vector<int*> v3;
    48. v3.push_back(new int(3));
    49. v3.push_back(new int(1));
    50. v3.push_back(new int(2));
    51. sort(v3.begin(), v3.end(), Less<int*>());
    52. return 0;
    53. }

    v1使用模板函数,v2,v3使用模板偏特化函数。

  • 相关阅读:
    chapter2——时钟和复位
    第一章操作系统引论
    软考考完后,你是否有这些疑问?
    docker network 组件内网
    计算机网络学习笔记(5.传输层 6.应用层)
    【Pytorch报错】RuntimeError:cuDNN error:CUDNN_STATUS_INTERNAL_ERROR 高效理解记录及解决!
    Java笔记(九)
    软件开发、网络空间安全、人工智能三个方向的就业和前景怎么样?哪个方向更值得学习?
    从零学习Linux操作系统 第三十五部分 Ansible中的角色
    奇点云:企业级数据基础设施的设计思路是“操作系统”
  • 原文地址:https://blog.csdn.net/zhang_si_hang/article/details/126126473