C++ 函数模板的重载与实参推断

2023-11-18

    结合网上的资料,对函数模板的重载与实参推断做一个总结。

函数模板的重载

  当需要对不同的类型使用同一种算法时,为了避免定义多个功能重复的函数,可以使用模板。然而,并非所有的类型都使用同一种算法,有些特定的类型需要单独处理,为了满足这种需求,C++允许对函数模板进行重载。

  例如,当交换基本类型和交换两个数组时,虽然功能都是交换,但是使用的方法却不相同,交换两个数组唯一的办法就是逐个交换所有的数组元素。

template<class T> void Swap(T &a, T &b){
    T temp = a;
    a = b;
    b = temp;
}
template<typename T> void Swap(T a[], T b[], int len){
    T temp;
    for(int i=0; i<len; i++){
        temp = a[i];
        a[i] = b[i];
        b[i] = temp;
    }
}

函数模板的实参

  在使用类模板创建对象时,需要显式的指明实参,例如:

template<typename T1, typename T2> class Point;
Point<int, int> p1(10, 20);  //在栈上创建对象
Point<char*, char*> *p = new Point<char*, char*>("东京180度", "北纬210度");  //在堆上创建对象

对于函数模板,调用函数时可以不显式的指明实参,编译器会自动推导出T的类型,例如:

//函数声明
template<typename T> void Swap(T &a, T &b);
//函数调用
int n1 = 100, n2 = 200;
Swap(n1, n2);
float f1 = 12.5, f2 = 56.93;
Swap(f1, f2);

模板实参推断过程中的类型转换

普通函数调用时的类型转换

  • 算数转换:例如 int 转换为 float,char 转换为 int,double 转换为 int 等。
  • 派生类向基类的转换:也就是向上转型,
  • const 转换:也即将非 const 类型转换为 const 类型,例如将 char * 转换为 const char *。
  • 数组或函数指针转换:如果函数形参不是引用类型,那么数组名会转换为数组指针,函数名也会转换为函数指针。
  • 用户自定的类型转换。

例如:

void func1(int n, float f);
void func2(int *arr, const char *str);
int nums[5];
char *url = "http://c.biancheng.net";
func1(12.5, 45);
func2(nums, url);

  对于 func1(),12.5 会从double转换为int,45 会从int转换为float;对于 func2(),nums 会从int [5]转换为int *,url 会从char *转换为const char *

函数模板调用时的类型转换

  对于函数模板,类型转换收到了更多的限制,仅能进行[const 转换]和[数组或函数指针转换],其他都不能应用于函数模板。

template<typename T> void func1(T a, T b);
template<typename T> void func2(T *buffer);
template<typename T> void func3(const T &stu);
template<typename T> void func4(T a);
template<typename T> void func5(T &a);

int name[20];
Student stu1("张华", 20, 96.5);  //创建一个Student类型的对象
func1(12.5, 30);  //Error
func2(name);  //name的类型从 int [20] 换转换为 int *,所以 T 的真实类型为 int
func3(stu1);  //非const转换为const,T 的真实类型为 Student
func4(name);  //name的类型从 int [20] 换转换为 int *,所以 T 的真实类型为 int *
func5(name);  //name的类型依然为 int [20],不会转换为 int *,所以 T 的真实类型为 int [20]

可以发现,当函数形参是引用类型时,数组不会转换为指针。

template<typename T> void func(T &a, T &b);

int str1[20];
int str2[10];
func(str1, str2);

  由于str1、str2的类型分别为int [20]和int [10],在函数调用过程中又不会转换为指针,所以编译器不知道应该将T实例化为int [20]还是int [10],导致调用失败

为函数模板显式地指明实参

  下面是一个实参推断失败的例子:

template<typename T1, typename T2> void func(T1 a){
    T2 b;
}
func(10);  //函数调用

func()有两个类型参数,分别是T1和T2,但是编译器只能推断出T1,不能推断出T2,调用失败

  显示指明的模板实参会按照从左到右的顺序与对应的模板参数匹配:第一个实参与第一个模板参数匹配,第二个实参与第二个模板参数匹配,只有尾部(最右)的类型参数的实参可以省略,而且前提是它们可以从传递给函数的实参中推断出来。 例如:

template<typename T1, typename T2> void func(T2 a){
    T1 b;
}
//函数调用
func<int>(10);  //省略 T2 的类型
func<int, int>(20);  //指明 T1、T2 的类型

显式的指明实参时可以应用正常的类型转换

  函数模板仅能进行[ const 转换 ]和[ 数组或函数指针转换 ]两种形式的类型转换,但是当我们显式的指明类型参数的实参时,就可以使用正常的类型转换了。例如:

template<typename T> void func(T a, T b);
func(10, 23.5);  //Error
func<float>(20, 93.7);  //Correct

  在第二种调用形式中,我们已经显式地指明了T的类型为float,编译器不会再为T的类型到底是int还是double而纠结了,所以可以从容地使用正常地类型转换了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 函数模板的重载与实参推断 的相关文章

  • 如何在MVVM中管理多个窗口

    我知道有几个与此类似的问题 但我还没有找到明确的答案 我正在尝试深入研究 MVVM 并尽可能保持纯粹 但不确定如何在坚持模式的同时启动 关闭窗口 我最初的想法是向 ViewModel 发送数据绑定命令 触发代码来启动一个新视图 然后通过 X
  • 如何检查图像对象与资源中的图像对象是否相同?

    所以我试图创建一个简单的程序 只需在单击图片框中更改图片即可 我目前只使用两张图片 所以我的图片框单击事件函数的代码 看起来像这样 private void pictureBox1 Click object sender EventArgs
  • 是否可以强制 XMLWriter 将元素写入单引号中?

    这是我的代码 var ptFirstName tboxFirstName Text writer WriteAttributeString first ptFirstName 请注意 即使我使用 ptFirstName 也会以双引号结束 p
  • 获取按下的按钮的返回值

    我有一个在特定事件中弹出的表单 它从数组中提取按钮并将标签值设置为特定值 因此 如果您要按下或单击此按钮 该函数应返回标签值 我怎样才能做到这一点 我如何知道点击了哪个按钮 此时代码返回 DialogResult 但我想从函数返回 Tag
  • 如何使用GDB修改内存内容?

    我知道我们可以使用几个命令来访问和读取内存 例如 print p x 但是如何更改任何特定位置的内存内容 在 GDB 中调试时 最简单的是设置程序变量 参见GDB 分配 http sourceware org gdb current onl
  • 如何避免情绪低落?

    我有一个实现状态模式每个状态处理从事件队列获取的事件 根据State因此类有一个纯虚方法void handleEvent const Event 事件继承基础Event类 但每个事件都包含其可以是不同类型的数据 例如 int string
  • 如何在列表框项目之间画一条线

    我希望能够用水平线分隔列表框中的每个项目 这只是我用于绘制项目的一些代码 private void symptomsList DrawItem object sender System Windows Forms DrawItemEvent
  • 实时服务器上的 woff 字体 MIME 类型错误

    我有一个 asp net MVC 4 网站 我在其中使用 woff 字体 在 VS IIS 上运行时一切正常 然而 当我将 pate 上传到 1and1 托管 实时服务器 时 我得到以下信息 网络错误 404 未找到 http www co
  • C - 找到极限之间的所有友好数字

    首先是定义 一对友好的数字由两个不同的整数组成 其中 第一个整数的除数之和等于第二个整数 并且 第二个整数的除数之和等于第一个整数 完美数是等于其自身约数之和的数 我想做的是制作一个程序 询问用户一个下限和一个上限 然后向他 她提供这两个限
  • C 预处理器库

    我的任务是开发源分析工具C程序 并且我需要在分析本身之前预处理代码 我想知道什么是最好的图书馆 我需要一些重量轻 便于携带的东西 与其推出自己的 为什么不使用cpp这是的一部分gcc suite http gcc gnu org onlin
  • Json.NET - 反序列化接口属性引发错误“类型是接口或抽象类,无法实例化”

    我有一个类 其属性是接口 public class Foo public int Number get set public ISomething Thing get set 尝试反序列化Foo使用 Json NET 的类给我一条错误消息
  • 在 ASP.NET Core 3.1 中使用包含“System.Web.HttpContext”的旧项目

    我们有一些用 Net Framework编写的遗留项目 应该由由ASP NET Core3 1编写的API项目使用 问题是这些遗留项目正在使用 System Web HttpContext 您知道它不再存在于 net core 中 现在我们
  • C# 中的递归自定义配置

    我正在尝试创建一个遵循以下递归结构的自定义配置部分
  • 将自定义元数据添加到 jpeg 文件

    我正在开发一个图像处理项目 C 我需要在处理完成后将自定义元数据写入 jpeg 文件 我怎样才能做到这一点 有没有可用的图书馆可以做到这一点 如果您正在谈论 EXIF 元数据 您可能需要查看exiv2 http www exiv2 org
  • 如何使我的表单标题栏遵循 Windows 深色主题?

    我已经下载了Windows 10更新包括黑暗主题 文件资源管理器等都是深色主题 但是当我创建自己的 C 表单应用程序时 标题栏是亮白色的 如何使我自己的桌面应用程序遵循我在 Windows 中设置的深色主题 你需要调用DwmSetWindo
  • 插入记录后如何从SQL Server获取Identity值

    我在数据库中添加一条记录identity价值 我想在插入后获取身份值 我不想通过存储过程来做到这一点 这是我的代码 SQLString INSERT INTO myTable SQLString Cal1 Cal2 Cal3 Cal4 SQ
  • 如何让Gtk+窗口背景透明?

    我想让 Gtk 窗口的背景透明 以便只有窗口中的小部件可见 我找到了一些教程 http mikehearn wordpress com 2006 03 26 gtk windows with alpha channels https web
  • Process.Start 阻塞

    我正在调用 Process Start 但它会阻止当前线程 pInfo new ProcessStartInfo C Windows notepad exe Start process mProcess new Process mProce
  • 如何使用 std::string 将所有出现的一个字符替换为两个字符?

    有没有一种简单的方法来替换所有出现的 in a std string with 转义 a 中的所有斜杠std string 完成此操作的最简单方法可能是boost字符串算法库 http www boost org doc libs 1 46
  • 使用 libcurl 检查 SFTP 站点上是否存在文件

    我使用 C 和 libcurl 进行 SFTP FTPS 传输 在上传文件之前 我需要检查文件是否存在而不实际下载它 如果该文件不存在 我会遇到以下问题 set up curlhandle for the public private ke

随机推荐

  • 最美应用API接口分析

    最美应用API接口分析 最美应用API接口分析一 请求版本列表1 1 API二 请求应用配置2 1 API2 2参数列表2 3 返回三 友盟更新3 1 API3 2参数列表3 3 返回四 appleStore应用信息4 1API4 2 返回
  • 发布npm包-简要记录

    1注册账号 注册npm账号 需要邮箱 激活npm账号 npm账号注册成功以后会收到邮件 邮件中有个链接 点进去进行激活 2创建项目 npm init 创建项目 name 命名规则 不能包含大写字母 空格及下滑线 version 创建时候默认
  • Shiro源码分析-初始化-SecurityManager

    源码分析的第一篇以SecurityManager的初始化为题 根据ini配置文件初始化shiro的代码主要为两段 解析ini文件为Ini对象 Factory
  • 电商行业常用指标

    首先要构建电商数据分析的基本指标体系 主要分为8个类指标 即 1 总体运营指标 从流量 订单 总体销售业绩 整体指标进行把控 起码对运营的电商平台有个大致了解 到底运营的怎么样 是亏是赚 2 网站流量指标 即对访问你网站的访客进行分析 基于
  • 【Python】pip安装源、pip config命令 及 pip安装包位置 等相关问题

    永久性添加pip安装源 查看pip文件的存储位置有 查看pip config 的配置方法 删除配置信息 查看pip下载的安装包的默认路径 查看如何修改安装位置 永久性添加pip安装源 pip config set global index
  • F5 BIG-IP LTM基础资料

    F5 BIG IP网络概述 TMOS是一个全代理的体系结构 流量必须穿越BIG IP设备以获得TMOS的优化效果 部署方式 路由模式 也被称作串联模式 真实服务器放在BIG IP之后的一个内部网络 真实服务器的网关需要指向 或者最终通过 B
  • qsort的基本用法

    qsort的基本用法 在我们日常的刷题中 我们经常遇见一些需要排序的问题 有的时候我们会直接运用循环以及选择结构来暴力排序 或者使用比较简单的冒泡排序等排序方法 这些都是直接运用我们C语言或者C 里的底层代码来实现 今天我将介绍一种较为简单
  • Unity3D中通过代码修改子物体层级的顺序

    今天有个同事问我如何在程序中修改子物体的层级关系来改变遮挡关系 我给他敲出来一句代码 UI的层级关系是通过渲染表现出来的 在canvas下的物体 排序越靠前的越先被渲染 这样一来就会 被后来渲染的遮挡 总结一下有三句代码是修改子物体的层级的
  • 用java实现输入成绩,判断等级

    用java里的Scanner类实现输入成绩 用if判断成绩等级 代码如下 用java实现输入成绩 判断等级 导包 import java util Scanner public class Exercise public static vo
  • k8s基础5——Pod常用命令、资源共享机制、重启策略和健康检查、环境变量、初始化容器、静态pod

    文章目录 一 基本了解 二 管理命令 三 yaml文件参数大全 四 创建pod的工作流程 五 资源共享机制 5 1 共享网络 5 2 共享存储 六 生命周期 重启策略 健康检查 七 环境变量 八 Init Containe初始化容器 九 静
  • 大神之路-起始篇

    欢迎关注 WeiyiGeek 公众号 点击 下方卡片 即可关注我哟 设为 星标 每天带你 基础入门 到 全栈实践 再到 放弃学习 涉及 网络安全运维 应用开发 物联网IOT 学习路径 个人感悟 等知识 花开堪折直须折 莫待无花空折枝 本章目
  • 【STM32学习】(19)STM32实现直流电机测转速(霍尔传感器)

    最近在学习STM32单片机 本次博文想记录一下32单片机连接霍尔传感器来测量直流电机转速 材料准备 1 单片机 STM32L052K8 2 霍尔传感器 3 直流电机 电路图如下 其中 单片机和直流电机不用介绍 下面介绍一下霍尔传感器 主要想
  • 二分查找算法(整数和浮点数)

    二分查找算法 一 整数二分模板 二 浮点数的二分 一 整数二分模板 二分核心思想 选择区间 每次都保证答案在被选择的区间内 循环往复 整数二分有两种情况 第一种是区间 l r 被划分成 l mid 和 mid 1 r 时使用 bool ch
  • 【记录】数据处理方法总结及实现

    记录 数据处理方法总结及实现 背景 数据增强作为前处理的关键步骤 在整个计算机视觉中有着具足轻重的地位 数据增强往往是决定数据集质量的关键 主要用于数据增广 在基于深度学习的任务中 数据的多样性和数量往往能够决定模型的上限 本次记录主要是对
  • Android中ImageView控件scaleType属性详解

    ImageView的具体属性 1 显示在ImageView的中心的属性 分别为 centerCrop center centerInside fitCenter 2 ImageView全部的属性 3 具体属性分析 android scale
  • 初学Python到月入过万最快的兼职途径(纯干货)

    1 兼职薪资 附行哥工资单 2 兼职门槛 附学习知识清单 3 兼职途径 附入职考核过程 4 行哥的兼职感受 答应行友的第一篇赚钱干货推文来啦 行哥第一个在读书期间通过兼职赚到的10w 收入 这也是初学Python小白最快达到月入过万的途径
  • java 内存溢出的代码_Java 常见内存溢出异常与代码实现

    Java 堆 OutOfMemoryError Java 堆是用来存储对象实例的 因此如果我们不断地创建对象 并且保证 GC Root 和创建的对象之间有可达路径以免对象被垃圾回收 那么当创建的对象过多时 会导致 heap 内存不足 进而引
  • python从键盘输入一个字符串、将小写字母全部_从键盘输入一个字符串_将其中的小写字母全部转换成大写字母...

    从键盘输入一个字符串 将其中的小写字母全部转换成大写字母 然后输出到一个磁盘文件 test 中保存 输入的字符串以 结束 我写的程序是 include include include void main char str 100 int i
  • Element Plus 实例详解(一)___安装设置

    Element Plus 实例详解 一 安装设置 本篇目录 一 前言 二 安装方法 1 环境支持 2 Element Plus安装使用方式 1 使用包管理器 2 浏览器直接引入 3 Element Plus引入方式使用小例子 三 Eleme
  • C++ 函数模板的重载与实参推断

    结合网上的资料 对函数模板的重载与实参推断做一个总结 函数模板的重载 当需要对不同的类型使用同一种算法时 为了避免定义多个功能重复的函数 可以使用模板 然而 并非所有的类型都使用同一种算法 有些特定的类型需要单独处理 为了满足这种需求 C