C++ 模板与泛型编程入门
C 模板与泛型编程入门模板把类型及非类型参数作为参数在编译期由编译器按用法生成具体函数或类是 C泛型编程与STL的基础。下文以Max、简单类模板、选择排序及可定制比较器为例说明常见写法排序复杂度为 (O(n^2))仅作模板演示工程中应使用std::sort等标准算法。目录从重复实现到函数模板模板实例化在编译期如何发生函数模板与类模板对照类模板与标准库的关系示例函数模板选择排序选择排序过程示意传入比较逻辑可调用对象小结参考链接从重复实现到函数模板若仅为不同类型各写一份「逻辑相同、仅类型不同」的函数维护成本高intmax_int(intx,inty){returnxy?x:y;}doublemax_double(doublea,doubleb){returnab?a:b;}函数模板将类型抽象为参数由调用处推导或显式指定templatetypenameTTmax_value(constTx,constTy){returnxy?x:y;}template typename T写成template class T等价引入类型形参T。调用max_value(1, 2)时通常推导出T为int编译器生成对应实例称为模板实例化。若实参类型不一致且无法统一推导需显式指定max_valuedouble(1, 2.0)等或调整设计如双类型形参。双类型形参示例两实参类型可不同templatetypenameT,typenameUautomax_mixed(constTa,constUb)-decltype(ab?b:a){returnab?b:a;}C14 起可写auto返回类型C20 起常用std::common_type_t或auto配合约束简化。模板实例化在编译期如何发生产物编译期源代码函数模板 max_value 定义调用 max_value 含 int 实参推导 T 为 int生成具体函数实例目标文件中的机器码模板默认在用到时实例化显式实例化template int max_valueint(const int, const int);可将定义固定到特定翻译单元用于控制编译时间或隐藏实现需配合设计。函数模板与类模板对照项目函数模板类模板引入方式template typename T R f(...)template typename T class C { ... };使用形态多数场景由实参推导T一般显式写Cint少数可 CTADC17典型用途算法、工具函数容器、资源管理、策略类关键字typename与class在类型形参上等价同左类模板容器、智能指针等常以类模板出现在类名后给出模板实参得到具体类型templatetypenameTclassBox{T content_{};public:voidset(constTv){content_v;}constTget()const{returncontent_;}};// Boxint、Boxstd::string 等为不同类类型std::vectorint、std::mapstd::string, int等同理。与标准库的关系STL容器多为类模板算法多为函数模板如std::sort、std::find通过迭代器与类型推导在不同容器上复用同一套算法接口。日常开发应优先使用标准库自定义模板多用于领域抽象或与库组合。容器类模板vectorlistmap迭代器区间begin 与 end算法函数模板sort / find / copy ...层次角色容器分配存储、提供begin()/end()迭代器抽象「位置」使算法与具体容器解耦算法只依赖迭代器类别能力随机访问、前向等示例函数模板选择排序以下用选择排序展示「同一套逻辑适用于多种T」要求T支持或通过下文方式定制比较。#includeiostream#includestringtemplatetypenameTboolless_than(constTa,constTb){returnab;}templatetypenameTvoidselection_sort(T*arr,intn){for(inti0;in-1;i){intmin_indexi;for(intji1;jn;j){if(less_than(arr[j],arr[min_index]))min_indexj;}if(min_index!i){T tmparr[i];arr[i]arr[min_index];arr[min_index]tmp;}}}templatetypenameTvoidprint_array(constT*arr,intn){for(inti0;in;i)std::coutarr[i](i1n? :\n);}int/double/std::string等已定义operator的类型可直接使用。数组长度在 C 中更惯用迭代器区间或std::spanC20此处沿用「指针 长度」便于与原文示例对照。选择排序过程示意每一轮在未排序后缀[i, n)中选最小元与位置i交换共约 (n-1) 轮。初始: [ 64, 25, 12, 22, 11 ] i0 选最小 11: [ 11, 25, 12, 22, 64 ] i1 选最小 12: [ 11, 12, 25, 22, 64 ] i2 选最小 22: [ 11, 12, 22, 25, 64 ] i3 选最小 25: [ 11, 12, 22, 25, 64 ] → 已有序第 i 轮在 arr[i..n-1] 中找最小下标 min_indexswap(arr[i], arr[min_index])i 从 0 递增到 n-2传入比较逻辑可调用对象若需按其它规则排序如按字符串长度可将比较操作做成可调用对象函数指针、函数对象、lambda并由模板形参Compare接收与std::sort(begin, end, comp)的思路一致#includeiostream#includestringstructStudent{std::string name;intscore{};};boolshorter_name_first(constStudenta,constStudentb){returna.name.size()b.name.size();}templatetypenameT,typenameComparevoidselection_sort_cmp(T*arr,intn,Compare comp){for(inti0;in-1;i){intmin_indexi;for(intji1;jn;j){if(comp(arr[j],arr[min_index]))min_indexj;}if(min_index!i){T tmparr[i];arr[i]arr[min_index];arr[min_index]tmp;}}}调用示例Student s[]{{Alice,90},{Bob,85},{Charlie,95},{David,88}};selection_sort_cmp(s,4,shorter_name_first);Compare常由编译器从实参推导亦可传入lambda无需单独命名比较函数。selection_sort_cmp(s,4,[](constStudenta,constStudentb){returna.scoreb.score;// 按分数降序});selection_sort_cmp调用端推导为 Comparelambda / 函数指针 / 函数对象模板形参 Comparecomp(a,b) 判定先后小结点说明复用一份模板定义多类型实例化减少重复逻辑类型检查实例化阶段检查能否调用comp、operator等优于盲目void*性能实例化后与普通函数类似抽象不必然带来运行时虚调用的开销工程实践复杂需求优先组合STL、概念C20 constraints、constexpr等现代特性学习用排序请用std::sort/std::ranges::sortC20 概念简述在包含concepts的前提下可用template std::totally_ordered T或requires约束T必须具备的操作错误信息更早、更清晰语义上仍属模板机制扩展。机制作用requires子句限定可实例化的类型集合concept命名一组约束便于复用if constexpr编译期分支避免对不可用分支实例化参考链接相关主题公开文章背景阅读https://mp.weixin.qq.com/s/zTHvLUVT0qSjFIyMsdhrhQ模板基础Templates - cppreference.com语法与实例化规则以当前采用的C 标准版本为准。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2453079.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!