当前位置: 首页 > news >正文

C++的模板简介

文章目录

    • 一、前言
    • 二、函数模板(Function Template)
    • 三、类模板(Class Template)
    • 四、变参模板(Variadic Template)
    • 五、模板的递归与元编程
    • 六、模板的局限与陷阱
    • 七、常用模板的实例
    • 八、C++20 的概念(Concepts)
    • 九、总结

一、前言

C++的模板(Template)是C++中一种强大的特性,它允许编写泛型程序,即编写不依赖于具体类型的代码。模板提供了一种机制,可以在编译时生成针对不同数据类型的代码,而不需要重复编写相同逻辑的代码。这种机制使得代码更加灵活和可重用。

二、函数模板(Function Template)

函数模板允许我们编写与具体类型无关的函数,从而使得函数能够处理不同的数据类型。函数模板的语法格式如下:

template<typename T1, typename T2,......,typename Tn>
返回值类型 函数名(参数列表)
{// 函数体
}
注意:typename是用来定义模板参数关键字,也可以使用class(切记:不能使用struct代替class)
template <typename T>
T max(T a, T b) {return (a > b) ? a : b;
}int main() {int x = 10, y = 20;double a = 5.5, b = 2.3;std::cout << max(x, y) << std::endl;  // 输出 20std::cout << max(a, b) << std::endl;  // 输出 5.5return 0;
}

在这里,typename T 表示模板参数T,它是一个占位符,表示函数中可以使用任意类型。当我们调用这个函数时,编译器会根据传递的参数类型自动推导出T的具体类型。

  • 模板类型参数与非类型模板参数

除了类型参数外,C++还支持非类型模板参数。非类型模板参数通常是一个整数或指针值,可以在编译时确定。例如:

template <typename T, int size>
T arraySum(T (&arr)[size]) {T sum = 0;for (int i = 0; i < size; ++i) {sum += arr[i];}return sum;
}

在这个例子中,size 是一个非类型模板参数,表示数组的大小。

  • 显式指定模板参数

虽然编译器通常可以推导出模板参数,但也可以显式地指定它们:

int a = max<int>(3, 7);

三、类模板(Class Template)

类模板允许定义一个通用的类,然后可以用不同的数据类型来实例化该类。典型的例子是标准库中的 std::vector 类,它是一个类模板,可以用来存储任意类型的元素。它的语法格式跟类模板类型,下面是一个简单的类模板示例:

template <typename T>
class Pair {
public:Pair(T first, T second) : first_(first), second_(second) {}T getFirst() const { return first_; }T getSecond() const { return second_; }private:T first_, second_;
};int main() {Pair<int> intPair(1, 2);Pair<std::string> stringPair("hello", "world");std::cout << intPair.getFirst() << ", " << intPair.getSecond() << std::endl;  // 输出 1, 2std::cout << stringPair.getFirst() << ", " << stringPair.getSecond() << std::endl;  // 输出 hello, worldreturn 0;
}
  • 模板特化(Template Specialization)

模板特化允许我们为特定类型提供模板的特殊实现。模板特化有两种形式:全特化部分特化全特化是为模板的特定类型提供完全不同的实现,下面这个例子实例化Pair< bool >时就会调用特化实现而不是通用实现:

template <typename T>
class Pair {
public:Pair(T first, T second) : first_(first), second_(second) {}T getFirst() const { return first_; }T getSecond() const { return second_; }private:T first_, second_;
};template <>
class Pair<bool> {
public:Pair(bool first, bool second) : bits((first ? 1 : 0) | (second ? 2 : 0)) {}bool getFirst() const { return bits & 1; }bool getSecond() const { return bits & 2; }private:int bits;
};

部分特化只适用于类模板,而不是函数模板,它允许为一部分模板参数提供特定实现:

template <typename T, typename U>
class Pair {
public:Pair(T first, U second) : first_(first), second_(second) {}void print() { std::cout << first_ << ", " << second_ << std::endl; }
private:T first_;U second_;
};// 部分特化版本,针对相同类型的 Pair
template <typename T>
class Pair<T, T> {
public:Pair(T first, T second) : first_(first), second_(second) {}void print() { std::cout << "Matching types: " << first_ << ", " << second_ << std::endl; }
private:T first_;T second_;
};

在这个例子中,当 Pair 的两个模板参数类型相同时,编译器会选择部分特化版本,而不是通用版本。

四、变参模板(Variadic Template)

C++11 引入了变参模板,允许模板接受可变数量的模板参数。这对处理不定数量的参数或类型非常有用。

template<typename... Args>
void print(Args... args) {(std::cout << ... << args) << std::endl;
}

在这个例子中,print函数可以接受任意数量的参数,并将它们打印出来。

五、模板的递归与元编程

模板递归和元编程是一种高级用法,允许在编译时进行复杂的计算和逻辑处理。典型的例子是计算编译时的斐波那契数列:

template<int N>
struct Fibonacci {static const int value = Fibonacci<N-1>::value + Fibonacci<N-2>::value;
};template<>
struct Fibonacci<1> {static const int value = 1;
};template<>
struct Fibonacci<0> {static const int value = 0;
};

这种编译期计算被称为模板元编程Template Metaprogramming),用于在编译期执行逻辑判断和计算。

六、模板的局限与陷阱

编译时间: 模板实例化会增加编译时间,尤其是对于大型代码库。
代码膨胀: 模板实例化会导致二进制文件膨胀,因为每种类型的实例化都会生成独立的代码。
错误信息复杂: 当模板代码出错时,编译器产生的错误信息通常较为复杂且难以理解。

七、常用模板的实例

STL 是 C++ 标准库的一部分,其中包含了大量的模板,如 std::vector, std::map, std::set 等。这些模板类使得开发者能够方便地使用各种数据结构和算法,而不必为每种类型单独实现。

八、C++20 的概念(Concepts)

C++20 引入了概念(Concepts),使得模板的类型约束更加明确。概念是一种用于限制模板参数的特性,可以显著提高模板代码的可读性和可维护性。

template <typename T>
concept Addable = requires(T a, T b) {{ a + b } -> std::convertible_to<T>;
};template <Addable T>
T add(T a, T b) {return a + b;
}

通过引入概念,编译器可以更早地检测出不满足条件的模板参数,从而减少复杂的编译错误信息。

九、总结

C++模板是一种功能强大且灵活的机制,能够极大地提高代码的复用性和类型安全性。模板的学习曲线较为陡峭,但一旦掌握,它将成为编写高效、通用代码的利器。C++20 的概念进一步增强了模板的表达能力,使得模板编程更加直观和强大。

相关文章:

C++的模板简介

文章目录 一、前言二、函数模板&#xff08;Function Template&#xff09;三、类模板&#xff08;Class Template&#xff09;四、变参模板&#xff08;Variadic Template&#xff09;五、模板的递归与元编程六、模板的局限与陷阱七、常用模板的实例八、C20 的概念&#xff08…...

树莓派5 笔记25:第一次启动与配置树莓派5_8G

今日继续学习树莓派5 8G&#xff1a;&#xff08;Raspberry Pi&#xff0c;简称RPi或RasPi&#xff09; 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 与 python 版本如下&#xff1a; 今日购得了树莓派5_8G版本&#xff0c;性能是同运…...

Melittin 蜂毒肽;GIGAVLKVLT TGLPALISWI KRKRQQ

【Melittin 蜂毒肽 简介】 蜂毒肽&#xff08;Melittin&#xff09;是蜜蜂毒液中的主要活性成分&#xff0c;由26个氨基酸组成&#xff0c;具有强碱性&#xff0c;易溶于水&#xff0c;是已知抗炎性最强的物质之一。蜂毒肽具有多种生物学、药理学和毒理学作用&#xff0c;包括…...

day32

更新源 cd /etc/apt/ sudo cp sources.list sources.list.save 将原镜像备份 sudo vim sources.list 将原镜像修改成阿里源/清华源&#xff0c;如所述 阿里源 deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiver…...

【clickhouse】 使用 SQLAlchemy 连接 ClickHouse 数据库的完整指南

我听见有人猜 你是敌人潜伏的内线 和你相知多年 我确信对你的了解 你舍命救我画面 一一在眼前浮现 司空见惯了鲜血 你忘记你本是娇娆的红颜 感觉你我彼此都那么依恋 &#x1f3b5; 许嵩《内线》 ClickHouse 是一款非常高效的开源列式数据库&#xff0c;因…...

按键收集单击,双击和长按

按键收集单击,双击和长按 引言 在我们生活中, 按键是必不可少的, 不同的电器, 有不同的按键, 但是按键总有不够用的时候, 那么给与一个按键赋予不同的功能,就必不可少了. 一个按键可以通过按下的时间长短和频次, 来定义其类型。 一次按键收集&#xff0c; 都是在一个按键收集周…...

进程的异常终止

进程的异常终止 进程收到了某些信号&#xff0c;他杀 进程自己调用abort函数&#xff0c;产生了SIGABRT(6)信号&#xff0c;自杀 进程的最后一个线程收到了"取消"操作&#xff0c;并且做出响应 如果进程是异常结束的&#xff0c;atexit\on_exit它们事先注册的遗言…...

并发编程 | Future是如何优化程序性能

在初识Future一文中介绍了Future的核心方法。本文中接着介绍如何用Future优化我们的程序性能。 在此之前&#xff0c;有必要介绍Future接口的一个实现类FutureTask。 FutureTask介绍 FutureTask继承结构 首先我们看一下FutureTask的继承结构&#xff1a; public class Futur…...

Oracle笔记

一、 如何解决 sqlplus 无法使用退格键和方向键 .bashrc 中添加如下内容&#xff0c;解决 退格键 stty erase ^h 安装 rlwap 后&#xff0c;执行如下命令可解决 方向键 rlwap sqlplus 二、 都有哪些备份数据到工具 三、 谈谈 你对 oracle 中实例和数据库的理解 数据库是一…...

LVS+Keepalived 双机热备

LVSKeepalived 双机热备 Keepalived案例分析Keepalived工具介绍Keepalived工具介绍一、功能特点 一、理解Keepalived实现原理实验报告资源列表一、安装keepalived以及ipvsadm Keepalived案例分析 企业应用中&#xff0c;单台服务器承担应用存在单点故障的危险单点故障一旦发生…...

Web Image scr图片从后端API获取基本实现

因系统开发中需求&#xff0c;会有页面显示图片直接从后端获取后显示&#xff0c;代码如下&#xff1a; 后端&#xff1a; /*** 获取图片流* param response* param fileName*/RequestMapping(value"getImgStream",method RequestMethod.GET)public void getImgStr…...

2024音频剪辑指南:探索四大高效工具!

音频剪辑不仅仅是技术活&#xff0c;更是一种艺术创作&#xff0c;它能够让声音更加生动、更具感染力。今天&#xff0c;我们就来探索几款优秀的音频剪辑工具。 福昕音频剪辑 链接&#xff1a;www.pdf365.cn/foxit-clip/ 福昕音频剪辑是一款界面简洁、操作直观的音频编辑软件…...

“CSS”第一步——WEB开发系列13

CSS (Cascading Style Sheets&#xff0c;层叠样式表&#xff09;&#xff0c;是一种用来为结构化文档&#xff08;如 HTML 文档或 XML 应用&#xff09;添加样式&#xff08;字体、间距和颜色等&#xff09;的计算机语言&#xff0c;CSS 文件扩展名为 .css。 一、什么是 CSS&a…...

IEEE802网络协议和标准

IEEE802网络协议和标准 802委员会IEEE 802介绍现有标准 IEEE 802.3介绍物理媒介类型MAC子层与LLC子层主要内容通讯标准POE供电标准802.3af、802.3at、802.3btIEEE802.3af的工作过程&#xff1a;IEEE802.3af主要供电参数&#xff1a;IEEE802.3af的分级参数&#xff1a;为什么会有…...

vulnhub靶机 DC-9(渗透测试详解)

一、靶机信息收集 1、靶机下载 https://download.vulnhub.com/dc/DC-9.zip 2、靶机IP扫描 3、探测靶机主机、端口、服务版本信息 4、靶机目录扫描 二、web渗透测试 1、访问靶机IP 查看页面功能点&#xff0c;发现一个搜索框和登录框 2、测试一下是否存在sql注入 查看当前数…...

javaweb的新能源充电系统pf

TOC springboot339javaweb的新能源充电系统pf 第1章 绪论 1.1 课题背景 二十一世纪互联网的出现&#xff0c;改变了几千年以来人们的生活&#xff0c;不仅仅是生活物资的丰富&#xff0c;还有精神层次的丰富。在互联网诞生之前&#xff0c;地域位置往往是人们思想上不可跨域…...

如何在桌面同时展示多个窗口

一、实现2分屏显示 win箭头 二、实现3分屏显示 1. 在实现2分屏显示的基础上&#xff0c;再次点击箭头图标&#xff0c;这次选择屏幕的上方或下方。 2. 点击后&#xff0c;第三个窗口将会出现在你选择的区域。现在&#xff0c;你可以在三个窗口之间自由切换&#xff0c;提高工…...

The Sandbox 游戏制作教程(第 5 部分):创建基于分类的系统

欢迎回到我们的系列&#xff0c;我们将记录 The Sandbox Game Maker 的 “On-Equip”&#xff08;装备&#xff09;功能的多种用途。 如果你刚加入 The Sandbox&#xff0c;装备功能是 “可收集组件”&#xff08;Collectable Component&#xff09;中的一个多功能工具&#x…...

HTML浏览器缓存(Browser Cache)

介绍&#xff1a; 浏览器缓存是Web缓存中最直接、最常见的一种形式。当浏览器首次请求某个资源时&#xff0c;如果服务器响应中包含了缓存控制指令&#xff08;如Cache-Control、Expires等&#xff09;&#xff0c;浏览器就会将这些资源存储在本地缓存中。后续请求相同资源时&a…...

短剧APP系统,推动短剧市场发展

近年来&#xff0c;短剧作为一直火爆的新兴行业&#xff0c;凭借着剧情进奏、爽、时长短等优势&#xff0c;深受大众欢迎&#xff0c;成为了大众碎片化时间的解压神器。 目前&#xff0c;随着短剧市场的快速发展&#xff0c;各个类型的短剧层出不穷&#xff0c;也推动了短剧AP…...

Vue 3.4+ 实验性/新特性深度实战(2026版)

一、背景&#xff1a;从“稳定”到“极致体验”截至 2026 年&#xff0c;Vue 3.4 与 3.5 已全面普及&#xff0c;但许多能​​显著降低心智负担​​的特性&#xff08;如 defineModel&#xff09;在早期被标记为“实验性”&#xff0c;或仅在 3.5 才完全稳定。如果你还在写“Pr…...

FireRedASR Pro在微信小程序开发中的应用:实时语音输入与转写

FireRedASR Pro在微信小程序开发中的应用&#xff1a;实时语音输入与转写 不知道你有没有这样的经历&#xff1a;用手机打字回复长消息时&#xff0c;手指按得发酸&#xff1b;或者在线听课时&#xff0c;想快速记下老师的重点&#xff0c;手速却跟不上语速。在移动优先的今天…...

像素风AI工具体验:像素史诗智识终端,让研究变得有趣又高效

像素风AI工具体验&#xff1a;像素史诗智识终端&#xff0c;让研究变得有趣又高效 1. 引言&#xff1a;当科研遇上像素冒险 想象一下&#xff1a;你是一位勇者&#xff0c;站在像素风格的城堡前&#xff0c;准备开始一场史诗般的冒险。但这次&#xff0c;你的武器不是剑与盾&…...

5个颠覆认知的无损视频处理能力:LosslessCut全解析

5个颠覆认知的无损视频处理能力&#xff1a;LosslessCut全解析 【免费下载链接】lossless-cut The swiss army knife of lossless video/audio editing 项目地址: https://gitcode.com/gh_mirrors/lo/lossless-cut 在数字内容创作爆炸的时代&#xff0c;视频处理已成为创…...

CefFlashBrowser:终极Flash浏览器解决方案,轻松玩转经典Flash游戏与课件

CefFlashBrowser&#xff1a;终极Flash浏览器解决方案&#xff0c;轻松玩转经典Flash游戏与课件 【免费下载链接】CefFlashBrowser Flash浏览器 / Flash Browser 项目地址: https://gitcode.com/gh_mirrors/ce/CefFlashBrowser 你是否还在为无法打开珍藏的Flash游戏而烦…...

DanKoe 视频笔记:原创思维指南:如何进行原创思考

在本教程中&#xff0c;我们将学习如何摆脱思维定式&#xff0c;培养真正的原创思考能力。我们将探讨为何独立思考如此困难&#xff0c;并提供一套实用的方法来帮助你形成自己的观点、连接不同领域的知识&#xff0c;并最终创造出有价值的内容。 概述 每个人都希望成为一个原创…...

Neeshck-Z-lmage_LYX_v2多场景落地:LoRA动态加载赋能数字人直播背景实时生成系统

Neeshck-Z-lmage_LYX_v2多场景落地&#xff1a;LoRA动态加载赋能数字人直播背景实时生成系统 1. 项目简介&#xff1a;一个专为本地绘画优化的轻量级工具 如果你对AI绘画感兴趣&#xff0c;特别是想体验国产的Z-Image文生图模型&#xff0c;但又被复杂的部署流程、繁琐的参数…...

OFA模型在零售行业的视觉问答应用案例

OFA模型在零售行业的视觉问答应用案例 1. 引言 走进任何一家现代零售商店&#xff0c;你都会看到成千上万的商品整齐地陈列在货架上。但对于店员来说&#xff0c;要快速准确地回答"这个品牌的洗发水有没有无硅油版本&#xff1f;"或者"这款饼干是否含有坚果成…...

Qwen2.5-VL视觉定位模型支持多目标检测:一句话同时定位‘人和汽车’,效果惊艳

Qwen2.5-VL视觉定位模型支持多目标检测&#xff1a;一句话同时定位"人和汽车"&#xff0c;效果惊艳 1. 视觉定位技术的新突破 在计算机视觉领域&#xff0c;视觉定位&#xff08;Visual Grounding&#xff09;技术正经历着革命性的进步。传统的目标检测方法需要预先…...

Copilot 插入广告引担忧,AI 工具商业化边界受考

Copilot 拉取请求中惊现广告插入团队成员使用 Copilot 纠正拉取请求&#xff08;PR&#xff09;中的拼写错误时&#xff0c;出现了令人意想不到的情况。Copilot 不仅修改了 PR 描述&#xff0c;还插入了它自身以及 Raycast 的广告。这一行为引发了用户的强烈反应&#xff0c;有…...