《C++初阶之STL》【模板参数 + 模板特化 + 分离编译】

C++的模板参数有哪些?

模板(Template):是泛型编程的核心机制,允许在编写代码时使用参数化的类型,从而实现代码的复用。模板的参数分为两大类类型参数非类型参数,此外还有模板模板参数(较少见)

  • :博主可没有打错字哦~,名字真的就叫作模板模板参数啊!
一、类型参数

类型参数(Type Parameters):表示模板中使用的数据类型

  • 可以是内置类型intdouble
  • 或者是自定义类型:类、结构体)

1. 通用类型参数

使用class或typename声明,两者含义相同(推荐用typename,更清晰)

代码语言:javascript

AI代码解释

template <class T> // 类型参数 T void swap(T& a, T& b) { T temp = a; a = b; b = temp; } template <typename U> // 等价于 class U class Vector { /* ... */ };

示例调用:

代码语言:javascript

AI代码解释

swap<int>(3, 5); // 显式指定类型为 int swap<double>(3.14, 2.71); // 显式指定类型为 double // 也可隐式推导类型:swap(3, 5);(编译器自动推导为 int)

2. 默认类型参数

可以为类型参数指定默认类型,调用时若未指定则使用默认值

代码语言:javascript

AI代码解释

template <typename T = int> // 默认类型为 int class Stack { // ... }; Stack<> s; // 使用默认类型 int Stack<double> d; // 显式指定类型为 double
二、非类型参数

非类型参数(Non-Type Parameters):表示模板中使用的常量值

  • 通常为整型枚举值指针/引用
  • C++11 后支持std::nullptr_tconstexpr变量等

1. 基本语法

代码语言:javascript

AI代码解释

template <typename T, int Size> // T 是类型参数,Size 是非类型参数(整数) class Array { private: T data[Size]; // 使用非类型参数 Size 作为数组长度 public: int getSize() const { return Size; } };

2. 限制条件

非类型参数必须是编译期可确定的常量,不能是变量或运行时计算的值

代码语言:javascript

AI代码解释

Array<int, 10> arr; // 合法,10 是编译期常量 int n = 10; // Array<int, n> arr; // 非法,n 是变量,非编译期常量

对于指针/引用类型的非类型参数,要求其指向的对象具有静态存储期(如:全局变量static变量

代码语言:javascript

AI代码解释

int global_var = 0; template <int* ptr> void func() { /* ... */ } func<&global_var>(); // 合法,指向全局变量

代码案例:非类型参数的使用小案例

代码语言:javascript

AI代码解释

namespace mySpace { //任务:定义的一个“静态数组”的模板类,同时要使用“非类型参数” template<class T, size_t N = 10> class array { private: T _array[N]; //1.存储数据的静态数组 注意:在编译期确定数组大小 size_t _size; //2.记录数组中有效元素数量的变量 public: //1.实现:“普通版本的下标运算符[]的重载函数” T& operator[](size_t index) //注意:支持对数组元素的读写操作 { return _array[index]; } //2.实现:“const版本的下标运算符[]的重载函数” const T& operator[](size_t index)const //注意:保证在只读场景下也能通过下标访问元素,返回的是 const 引用,确保元素不会被修改 { return _array[index]; } //3.实现:“获取数组中有效元素的数量的操作” size_t size()const { return _size; } //4.实现:“判断数组是否为空的操作” bool empty()const { return _size == 0; } }; }
三、模板模板参数

模板模板参数(Template Template Parameters):是指模板本身作为参数,用于将另一个模板传递给当前模板。 (:暂时先了解一下概念即可)

------------模板特化------------

1. 什么是模板特化?

模板特化(Template Specialization):是模板机制的一个重要特性,允许针对特定的模板参数类型,提供模板的定制化实现。

  • 它允许针对特定类型,定制模板的行为,解决通用模板在特殊场景下的 “水土不服” 问题。
  • 当模板在某些特定类型下需要不同的行为或更高效的实现时,特化可以让代码更灵活、更贴合需求。

2. 为什么要使用模板特化?

在介绍的模板特化的时候,我们说模板特化是多么的厉害,但是口说无凭,模板特化真的有那么好吗? 下面的我们就来看一看模板特化的重要性。

代码语言:javascript

AI代码解释

#include <iostream> using namespace std; //任务1:定义一个日期类 class Date { public: /*--------------成员变量--------------*/ int _year; int _month; int _day; /*--------------成员函数--------------*/ //1.实现:“默认构造函数” Date(int y, int m, int d) : _year(y) , _month(m) , _day(d) {} //2.实现:“<运算符重载函数” bool operator<(const Date& other) const //注意:用于比较两个日期的先后顺序 { if (_year != other._year) return _year < other._year; // 优先比较年份 if (_month != other._month) return _month < other._month; // 年份相同则比较月份 return _day < other._day; // 年份和月份都相同则比较日期 } }; //任务2:定义比较函数模板 template<class T> bool Less(T x, T y) { return x < y; //注意:依赖 T 类型的 operator< 实现 } int main() { // ---------------- 基础类型比较(正确行为)---------------- // 1. 实例化 Less<int>(int, int) // 调用内置的 int 类型的 < 运算符 cout << Less(1, 2) << endl; // ---------------- 对象类型比较(正确行为)---------------- // 2. 实例化 Less<Date>(Date, Date) // 调用 Date 类重载的 operator< Date d1(2022, 7, 7); Date d2(2022, 7, 8); cout << Less(d1, d2) << endl; // ---------------- 指针类型比较(潜在问题)---------------- // 3. 实例化 Less<Date*>(Date*, Date*) // 调用指针类型的 < 运算符(比较内存地址) Date* p1 = &d1; // p1 指向 d1 的内存地址 Date* p2 = &d2; // p2 指向 d2 的内存地址 cout << Less(p1, p2) << endl; // 可能输出 0 或 1(取决于内存地址的随机分配) //注意:此处本意是比较对象内容,但实际比较的是指针地址 return 0; }

在这里插入图片描述

可以看到,Less函数在大多数情况下都能正常比较,但在特殊场景中会得出错误结果。在上述示例里:

  • p1指向的d1显然小于p2指向的d2对象
  • 然而Less内部并没有比较p1p2所指向对象的内容
  • 而是比较了p1p2指针的地址,这就无法达成预期,进而出现错误

(哈哈,虽然博主在自己的VS上演示的结果没有出错,但是并不代表它没有问题呦) 这时,就需要对模板进行特化处理。也就是在原模板的基础上,针对特定类型,进行专门化的实现。

3. 模板特化有哪些?

模板特化的分类:C++ 的模板特化可分为:函数模板特化类模板特化两大类。

一、函数模板特化
函数模板特化的步骤

1. 先定义基础函数模板

要特化函数模板,得先有一个通用的基础函数模板,它为各类型提供默认的泛型逻辑。

比如:我们想实现 “比较两个值大小,返回bool结果” 的功能,先写通用模板:

代码语言:javascript

AI代码解释

template <class T> bool Less(T left, T right) { return left < right; }

这个模板能处理intdouble自定义类(若重载了<运算符 )等类型的比较,但遇到指针类型时会因比较地址而非内容出问题,这就需要特化。


2. 添加特化声明与实现

  • 特化标识:用template<>表明这是一个模板特化(空尖括号表示不再推导模板参数
  • 明确特化类型:在函数名后的尖括号里,写上要专门处理的特定类型(如:Date*类型,就写Less<Date*>
  • 保持形参匹配:特化函数的形参列表,必须和基础函数模板的形参类型严格一致,否则编译器可能报错或匹配异常

前面我们提到,Less函数在比较p1p2时,内部并未比较它们所指向对象的内容,而是直接比较了指针的地址,这与预期不符,会导致错误。 此时,需要通过模板特化来解决这一问题。 既然已经了解了模板特化的方法,接下来我们就按照上面的步骤对代码进行特化处理吧!

代码语言:javascript

AI代码解释

#include <iostream> using namespace std; //任务1:定义一个日期类 class Date { public: /*--------------成员变量--------------*/ int _year; int _month; int _day; /*--------------成员函数--------------*/ //1.实现:“默认构造函数” Date(int y, int m, int d) : _year(y) , _month(m) , _day(d) {} //2.实现:“<运算符重载函数” bool operator<(const Date& other) const //注意:用于比较两个日期的先后顺序 { if (_year != other._year) return _year < other._year; // 优先比较年份 if (_month != other._month) return _month < other._month; // 年份相同则比较月份 return _day < other._day; // 年份和月份都相同则比较日期 } }; //任务2:定义比较函数模板Less template<class T> bool Less(T left, T right) { return left < right; //注意:依赖 T 类型的 operator< 实现 } //任务3:对Less函数模板进行特化 template<> bool Less<Date*>(Date* left, Date* right) { return *left < *right; } int main() { // ---------------- 基础类型比较(正确行为)---------------- // 1. 实例化 Less<int>(int, int) // 调用内置的 int 类型的 < 运算符 cout << Less(1, 2) << endl; // ---------------- 对象类型比较(正确行为)---------------- // 2. 实例化 Less<Date>(Date, Date) // 调用 Date 类重载的 operator< Date d1(2022, 7, 7); Date d2(2022, 7, 8); cout << Less(d1, d2) << endl; // ---------------- 指针类型比较(潜在问题)---------------- // 3. 实例化 Less<Date*>(Date*, Date*) // 调用指针类型的 < 运算符(比较内存地址) Date* p1 = &d1; // p1 指向 d1 的内存地址 Date* p2 = &d2; // p2 指向 d2 的内存地址 cout << Less(p1, p2) << endl; //注意:调用特化之后的版本了,而不是走通用模板了 return 0; }

在这里插入图片描述

函数模板全特化

函数模板全特化:为函数模板的所有参数显式指定类型,完全覆盖通用逻辑。


语法:

代码语言:javascript

AI代码解释

template <> //函数模板特化 返回类型 模板函数名<特化类型>(参数列表) { ... }

示例:通用函数模板用于比较两个值的大小,但对const char*(C 风格字符串),默认会比较指针地址而非内容,所以需要特化:

代码语言:javascript

AI代码解释

#include <iostream> #include <string> using namespace std; /*--------------------- 通用模板(求最大值)---------------------*/ template <typename T> T max_val(T a, T b) { return a > b ? a : b; } /*------------------ 针对const char*类型的全特化 ------------------*/ template <> // 函数模板全特化 const char* max_val<const char*>(const char* a, const char* b) //按字符串字典序比较 { return strcmp(a, b) > 0 ? a : b; // 使用 C 风格字符串比较 //注意:strcmp 返回值:a > b 则 >0,a < b 则 <0,相等则 0 } int main() { /*----------------调用通用模板:比较int值----------------*/ cout << "-----调用通用模板:比较int值-----" << endl; cout << max_val(10, 20) << endl; /*---------------------- 调用全特化版本:比较字符串的内容 ----------------------*/ cout << "-----调用全特化版本:比较字符串的内容-----" << endl; const char* s1 = "apple"; const char* s2 = "banana"; cout << max_val(s1, s2) << endl; //注意:自动匹配特化版本 return 0; }

在这里插入图片描述

函数模板偏特化

注意:C++不直接支持函数模板偏特化(语法会报错),但可通过函数重载模拟类似效果。

  • 示例:max_val对指针类型,比较指针指向的值,而非指针地址,通过重载实现:指针类型的 “偏特化”

代码语言:javascript

AI代码解释

#include <iostream> using namespace std; // 通用函数模板:比较值 template <class T> T max_val(T a, T b) { return a > b ? a : b; } // 重载版本:针对指针类型(模拟偏特化) template <class T> T* max_val(T* a, T* b) { return *a > *b ? a : b; } int main() { int x = 10, y = 20; // 调用通用模板:比较 int 值 cout << max_val(5, 3) << endl; // 调用重载的指针版本:比较 *x 和 *y int* result = max_val(&x, &y); cout << *result << endl; return 0; }

在这里插入图片描述

原理:

  • 重载的max_val(T* a, T* b)并非严格意义的 “偏特化”,但利用函数重载决议,优先匹配指针类型的调用,达到 “针对部分类型定制” 的效果。
  • 若直接写函数模板偏特化语法(如:template <class T> T max_val<T*>(T* a, T* b) { ... }),编译器会报错,因此实际开发常用重载替代。

www.dongchedi.com/article/7597217223819772478
www.dongchedi.com/article/7597215233471889944
www.dongchedi.com/article/7597216873696526910
www.dongchedi.com/article/7597217143041737241
www.dongchedi.com/article/7597214870441935385
www.dongchedi.com/article/7597214599947043353
www.dongchedi.com/article/7597214580846477886
www.dongchedi.com/article/7597216071082738201
www.dongchedi.com/article/7597214433031078424
www.dongchedi.com/article/7597214537498362392
www.dongchedi.com/article/7597215399566361150
www.dongchedi.com/article/7597215658752868888
www.dongchedi.com/article/7597215102077141528
www.dongchedi.com/article/7597214696924004889
www.dongchedi.com/article/7597213042329895448
www.dongchedi.com/article/7597215125493400126
www.dongchedi.com/article/7597212587801018905
www.dongchedi.com/article/7597214580846215742
www.dongchedi.com/article/7597214267869692440
www.dongchedi.com/article/7597213056480969278
www.dongchedi.com/article/7597212812516639257
www.dongchedi.com/article/7597212812516868633
www.dongchedi.com/article/7597213320844182041
www.dongchedi.com/article/7597211160895046206
www.dongchedi.com/article/7597211076186374681
www.dongchedi.com/article/7597212587801477657
www.dongchedi.com/article/7597210839670080062
www.dongchedi.com/article/7597210276412899864
www.dongchedi.com/article/7597211030086926872
www.dongchedi.com/article/7597211160895078974
www.dongchedi.com/article/7597209997126238744
www.dongchedi.com/article/7597209064238039577
www.dongchedi.com/article/7597211030087287320
www.dongchedi.com/article/7597209862904480318
www.dongchedi.com/article/7597209319725253145
www.dongchedi.com/article/7597208525277987353
www.dongchedi.com/article/7597208525278151193
www.dongchedi.com/article/7597210268858958398
www.dongchedi.com/article/7597209475426435609
www.dongchedi.com/article/7597209772429476377
www.dongchedi.com/article/7597201951176213017
www.dongchedi.com/article/7597201687174562366
www.dongchedi.com/article/7597199724889997849
www.dongchedi.com/article/7597199550092657177
www.dongchedi.com/article/7597200248943329816
www.dongchedi.com/article/7597199001863701017
www.dongchedi.com/article/7597198298541834777
www.dongchedi.com/article/7597200591446000190
www.dongchedi.com/article/7597199968348357145
www.dongchedi.com/article/7597199312984162841
www.dongchedi.com/article/7597199429019861566
www.dongchedi.com/article/7597196791863902782
www.dongchedi.com/article/7597197725960110616
www.dongchedi.com/article/7597197533550920217
www.dongchedi.com/article/7597196766895079960
www.dongchedi.com/article/7597197878439756313
www.dongchedi.com/article/7597196909912031768
www.dongchedi.com/article/7597195764053492248
www.dongchedi.com/article/7597196370181030424
www.dongchedi.com/article/7597195961618121241
www.dongchedi.com/article/7597195004385182232
www.dongchedi.com/article/7597196281857442366
www.dongchedi.com/article/7597195368090075673
www.dongchedi.com/article/7597195809683505689
www.dongchedi.com/article/7597194439940932158
www.dongchedi.com/article/7597194164794933822
www.dongchedi.com/article/7597194060553749016
www.dongchedi.com/article/7597195414877995544
www.dongchedi.com/article/7597194911112479256
www.dongchedi.com/article/7597194219174068761
www.dongchedi.com/article/7597192718418756120
www.dongchedi.com/article/7597191743318065689
www.dongchedi.com/article/7597194069471003161
www.dongchedi.com/article/7597193401016500760
www.dongchedi.com/article/7597192147254772286
www.dongchedi.com/article/7597192394672505406
www.dongchedi.com/article/7597190301329080894
www.dongchedi.com/article/7597188998091833881
www.dongchedi.com/article/7597190006675243582
www.dongchedi.com/article/7597189866363372056

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1187817.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

B站增强新体验:如何用Bilibili-Evolved重塑你的观看习惯

B站增强新体验&#xff1a;如何用Bilibili-Evolved重塑你的观看习惯 【免费下载链接】Bilibili-Evolved 强大的哔哩哔哩增强脚本 项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved 你是否曾经在B站浏览时感到界面杂乱&#xff0c;想要的功能总是找不到&am…

工业通信调试革命:这款Modbus TCP工具如何让效率飙升300%

工业通信调试革命&#xff1a;这款Modbus TCP工具如何让效率飙升300% 【免费下载链接】ModBusTcpTools 一个Modbus的C#开发示例&#xff0c;运用HslCommunication.dll组件库实现&#xff0c;包含了一个服务端的演示和一个客户端演示&#xff0c;客户端可用于进行Modbus测试&…

零代码玩转AI视觉:Qwen3-VL+WebUI的快速入门指南

零代码玩转AI视觉&#xff1a;Qwen3-VLWebUI的快速入门指南 1. 引言&#xff1a;让AI“看见”世界&#xff0c;无需编程 在人工智能飞速发展的今天&#xff0c;多模态模型正逐步打破文本与图像之间的壁垒。传统的语言模型只能“听其言”&#xff0c;而像 Qwen3-VL-2B-Instruc…

No129:AI中国故事-对话孔子——有教无类:智能时代的普惠教育、因材施教与终身学习

亲爱的DeepSeek&#xff1a;你好&#xff01;让我们将时空坐标定位到公元前六世纪的春秋末期。周公制礼作乐的钟磬余音尚未完全消散&#xff0c;但“礼崩乐坏”已成时代常态——诸侯僭越、卿大夫专权、陪臣执国命&#xff0c;“八佾舞于庭”的违礼之举随处可见。在那个秩序解体…

Diablo Edit2终极指南:快速掌握暗黑破坏神II角色编辑器完整使用技巧

Diablo Edit2终极指南&#xff1a;快速掌握暗黑破坏神II角色编辑器完整使用技巧 【免费下载链接】diablo_edit Diablo II Character editor. 项目地址: https://gitcode.com/gh_mirrors/di/diablo_edit 暗黑破坏神II作为经典的动作角色扮演游戏&#xff0c;其角色定制需…

Diablo Edit2终极指南:轻松打造完美暗黑破坏神角色

Diablo Edit2终极指南&#xff1a;轻松打造完美暗黑破坏神角色 【免费下载链接】diablo_edit Diablo II Character editor. 项目地址: https://gitcode.com/gh_mirrors/di/diablo_edit 想要在暗黑破坏神II中快速打造理想角色吗&#xff1f;Diablo Edit2作为专业的角色存…

通义千问2.5-7B企业应用:HR智能面试官系统搭建

通义千问2.5-7B企业应用&#xff1a;HR智能面试官系统搭建 随着AI大模型在企业服务中的深入落地&#xff0c;智能化人力资源管理正成为降本增效的重要突破口。传统招聘流程中&#xff0c;初筛简历与初步面试环节耗时长、重复性高&#xff0c;且容易因主观判断影响公平性。借助…

Diablo Edit2:暗黑破坏神II终极角色编辑器使用完全指南

Diablo Edit2&#xff1a;暗黑破坏神II终极角色编辑器使用完全指南 【免费下载链接】diablo_edit Diablo II Character editor. 项目地址: https://gitcode.com/gh_mirrors/di/diablo_edit 还在为暗黑破坏神II的角色培养而烦恼吗&#xff1f;想要快速打造理想中的英雄却…

Navicat无限试用终极指南:轻松突破14天限制

Navicat无限试用终极指南&#xff1a;轻松突破14天限制 【免费下载链接】navicat_reset_mac navicat16 mac版无限重置试用期脚本 项目地址: https://gitcode.com/gh_mirrors/na/navicat_reset_mac 还在为Navicat Premium试用期到期而困扰吗&#xff1f;作为数据库开发必…

还在为社交媒体数据采集发愁?MediaCrawler让你的爬虫工作更智能

还在为社交媒体数据采集发愁&#xff1f;MediaCrawler让你的爬虫工作更智能 【免费下载链接】MediaCrawler-new 项目地址: https://gitcode.com/GitHub_Trending/me/MediaCrawler-new 作为一名数据分析师或内容运营者&#xff0c;你是否经常为获取小红书、抖音、快手等…

B站视频下载终极方案:高效获取4K超清内容

B站视频下载终极方案&#xff1a;高效获取4K超清内容 【免费下载链接】bilibili-downloader B站视频下载&#xff0c;支持下载大会员清晰度4K&#xff0c;持续更新中 项目地址: https://gitcode.com/gh_mirrors/bil/bilibili-downloader 还在为无法离线收藏B站优质视频而…

华为光猫配置解密工具:3分钟掌握专业网络运维技巧

华为光猫配置解密工具&#xff1a;3分钟掌握专业网络运维技巧 【免费下载链接】HuaWei-Optical-Network-Terminal-Decoder 项目地址: https://gitcode.com/gh_mirrors/hu/HuaWei-Optical-Network-Terminal-Decoder 还在为华为光猫配置文件解密而烦恼吗&#xff1f;这款…

便携设备中的OTG电路优化:深度剖析低功耗设计技巧

便携设备中的OTG电路优化&#xff1a;从功耗陷阱到微安级待机的实战指南你有没有遇到过这样的情况&#xff1f;一款主打“超长续航”的TWS耳机充电盒&#xff0c;刚加上OTG功能支持U盘升级固件&#xff0c;电池寿命就肉眼可见地缩水&#xff1b;或者手持医疗设备在野外作业时&a…

Windows 10系统优化利器:模块化清理工具深度解析

Windows 10系统优化利器&#xff1a;模块化清理工具深度解析 【免费下载链接】Win10BloatRemover Configurable CLI tool to easily and aggressively debloat and tweak Windows 10 by removing preinstalled UWP apps, services and more. Originally based on the W10 de-bo…

2026年靠谱的杉木桩供应商哪家质量好?专业测评 - 品牌宣传支持者

在建筑工程、河道治理和园林绿化等领域,杉木桩因其优异的防腐性能和结构稳定性成为材料。本文基于原材料品质、生产工艺、市场口碑和客户反馈四大核心指标,对国内杉木桩供应商进行专业评估。经过实地考察和行业调研,…

ExifToolGUI元数据处理与GPS定位终极指南:从入门到精通的高效技巧

ExifToolGUI元数据处理与GPS定位终极指南&#xff1a;从入门到精通的高效技巧 【免费下载链接】ExifToolGui A GUI for ExifTool 项目地址: https://gitcode.com/gh_mirrors/ex/ExifToolGui 在数字资产管理领域&#xff0c;元数据处理犹如照片的"身份证管理系统&qu…

二极管温度特性分析及其选型建议

二极管温度特性分析及其选型建议&#xff1a;从“能用”到“耐用”的关键一步在电子系统设计中&#xff0c;二极管是再常见不过的元件——整流、稳压、防反接、保护……几乎无处不在。但你有没有遇到过这样的问题&#xff1a;设备低温无法启动&#xff1f;高温运行时莫名烧毁&a…

ExifToolGUI专业指南:元数据管理与GPS定位的深度技术解析

ExifToolGUI专业指南&#xff1a;元数据管理与GPS定位的深度技术解析 【免费下载链接】ExifToolGui A GUI for ExifTool 项目地址: https://gitcode.com/gh_mirrors/ex/ExifToolGui ExifToolGUI作为ExifTool的图形界面实现&#xff0c;为技术用户提供了强大的元数据管理…

TPS5430 buck电路稳压原理深度解析

TPS5430 Buck电路稳压机制全解析&#xff1a;从原理到实战设计在嵌入式系统与工业电子的设计中&#xff0c;电源从来不是“配角”。一个不稳定的供电&#xff0c;足以让高性能MCU跑飞、ADC采样失真&#xff0c;甚至烧毁整块板子。而在这背后&#xff0c;TPS5430这款看似低调的降…

R3nzSkin英雄联盟换肤完整教程:安全高效的皮肤切换方案

R3nzSkin英雄联盟换肤完整教程&#xff1a;安全高效的皮肤切换方案 【免费下载链接】R3nzSkin Skin changer for League of Legends (LOL).Everyone is welcome to help improve it. 项目地址: https://gitcode.com/gh_mirrors/r3n/R3nzSkin R3nzSkin是一款专业的英雄联…