变长参数表va_list,模板template,打造通用函数

2023-11-09

假设我想写一个支持变长参数的max函数。

template <typename T>
T max(T first_arg, ...)
{
    if (first_arg == ???)                   // Q1.
        return ???;                         // Q2.

    va_list ap;
    va_start(ap, first_arg);

    T tmp, ret_val = ???;                   // Q3.
    while((tmp = va_arg(ap, T)) != ???)     // Q4.
    {
        if (tmp > ret_val)
            ret_val = tmp;
    }
    va_end(ap);
    return ret_val;
}

关于变长参数如何确定长度,官方给出两个方案:

h2. 1. 第一个参数为参数数量,这个很容易想到。(见示例代码max)

h2. 2. 最后一个参数为特殊字符,就像字符数组以\0结尾那样。

对于第二个方案,这个特殊字符到底得特殊到什么程度,很难确定。
对int类型来讲,可以定为INT_MIN
对double类型来讲,可以定为DOUBLE_MIN

我们知道变长参数表,需要这样定义
va_list ap;
va_start(ap, first_arg);

接着我们就要去遍历这个ap了,何时遍历结束呢?
while (T tmp = va_arg(ap, T))
{
if (tmp == ???)
break;
}

也不保证,max只有一个参数(也就是结束符)
那又得怎么判断 first_arg == ??? 返回什么值呢?

综上所述,对于变长参数表的max函数,第二个方案不太可行。
我们要弃用while,改用更安全的for循环,也就是说, 在遍历之前,就已经能确定比较次数

不过,template的模板形参,不仅支持参数类型,而且支持参数数值,在这里实际上还有第三种方案:

h2. 3. 使用template,模板实参指定传入参数数量。(见示例代码min)

完整示例代码如下

#include <iostream>
#include <limits.h>
#include <stdarg.h>
using namespace std;

template <typename T>
T max(T n, ...)
{
    int len = static_cast<int>(n);      // 强制转换很无奈

    va_list ap;
    va_start(ap, n);

    T ret_val = T(INT_MIN);             // 这个INT_MIN初始化很无奈
    for (T i = 0; i < len; ++i)
    {
        T tmp = va_arg(ap, T);
        if (tmp > ret_val)
            ret_val = tmp;
    }

    va_end(ap);

    return ret_val;
}

template <int len, typename T>
T min(T first, ...)
{
    va_list ap;
    va_start(ap, first);

    T ret_val = first;
    for (T i = 0; i < len - 1; ++i)     // 因为len是参数总数,第一个参数已经给了ret_val,所以这里的比较次数-1
    {
        T tmp = va_arg(ap, T);
        if (tmp < ret_val)
            ret_val = tmp;
    }

    va_end(ap);

    return ret_val;
}

int main()
{
    cout << max(3,1,2,4) << endl;
    cout << min<4>(9, 2, 6, 4) << endl;                 // 模板实参参数类型甚至可以省略,这里函数实例根据参数确定为int
    cout << min<4, int>(9, 2, 1, 4) << endl;

    cout << max(3.0, 1.6, 2.8, 4.9) << endl;            // 第一个参数一定要写成3.0,不能写成3(将后续参数类型约束为double类型)
    cout << min<4>(0.9, 2.2, 6.3, 4.7) << endl;
    return 0;
}

且看方案一的强制转换部分和初始化部分,相较而言,方案三好太多。

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

变长参数表va_list,模板template,打造通用函数 的相关文章

  • 微服务实践--微服务方法论00

    思想 在接收到一个新的新项目时 架构师的职责是建立项目的业务与技术实现之间的桥梁 在翻译业务到技术实现的过程中需要进行业务建模 技术设计等方面的工作 业务建模和技术设计过程中都有各自领域的知识体系 基本上每个知识体系都是由上层的理论 概念和
  • 太牛逼了!从Python入门到入魔

    总被读者问到 我看完了python入门的书 后面就不知道要学什么了 今天就给你们整理全套入门到进阶的教程 这套教程非常全面而且详细 从Python入门到Python进阶 Django Flask等Web框架以及爬虫 数据库 算法与数据结构等
  • 解决k8s集群环境内存不足导致容器被kill问题

    背景 最近线上环境上出现了一个问题 k8s集群环境Pod中的tomcat容器运行一段时间后直接被killd 但有时一切看起来正常 不能准确判断在什么时机出现被Killd问题 本文就此问题介绍了Linux内存不足原因以及为什么特定进程会被杀死
  • 二面字节被问到VARCHAR(M) 到底占用多少个字节?我跟面试官硬刚了半小时

    前言 这个问题其实很有迷惑性 问的是字节 不是字符 我们知道在计算机中只能存储二进制数据 所以要搞清楚这个问题 就要搞清楚下面2个问题 1 字节和字符的对应关系 2 varchar 到底能存多少个字节 为了搞清楚上面两个问题 又必须搞清楚m
  • python学习笔记——条件判断

    上篇 https blog csdn net qq 42489308 article details 89388218 条件判断 条件判断是通过一条或多条判断语句的执行结果 True或者False 来决定执行的代码块 在Python语法中
  • Python实现“鸟脸识别”系统,看看什么鸟最贪吃~ 初学者也能学会

    梦晨 发自 凹非寺 量子位 报道 公众号 QbitAI 网友cldud1245是一个鸟类爱好者 以下简称喂鸟哥 最近打算自学Python 拥有其他语言编程经验的他 可不打算按部就班从Hello World做起 一上来就挑战图像识别 他用一个
  • 为什么程序员都喜欢安静?

    大家回顾一下上学期间 你在上晚自习想完成今天老师布置的作业 但是你的班级却非常的吵闹 跟置身在菜市场一样 你能专心完成作业吗 不受周围吵闹环境的影响吗 相信大部分的人都难以静下心来认真完成作业 有时候好不容易想到一个思路 结果旁边的人拍你一
  • 如何写一篇简洁易懂的测试报告?

    一 什么是测试报告 测试报告是指把测试的过程和结果写成文档 对发现的问题和缺陷进行分析 为纠正软件的存在的质量问题提供依据 同时为软件验收和交付打下基础 二 测试报告的内容 测试报告的内容可以总结为以下目录 首页 引言 目的 背景 缩略语
  • 基于DS18B20和HS1101的仓库自动报警系统

    基于DS18B20和HS1101的仓库自动报警系统 背景介绍 效果展示 完整版的项目代码 仿真文件 下面是项目原理图 具体管脚定义如下图 18B20温度原理 HS1101湿度传感器 红外测距报警模块我用到的是GP2D12 通过数模转化器AD
  • Redis 的五种基本类型(实战篇)

    良心公众号 关注不迷路 Redis 是一个速度非常快的非关系型数据库 它可以存储键 key 与 5 种不同类型的值 value 之间的映射 可以将存储在内存的键值对数据持久化到硬盘 可以使用复制特性来扩展读性能 还可以使用客户端分片来扩展性
  • 用Python帮忙找指定小说最新更新且网速最快的网站

    一 引言 这个五一假期自驾回老家乡下 家里没装宽带 用手机热点方式访问网络 这次回去感觉4G信号没有以前好 通过百度查找小说最新更新并打开小说网站很慢 有时要打开好多个网页才能找到可以正常打开的最新更新 为了躲懒 老猿决定利用Python爬
  • 8个适合新手的Python小项目

    这是我挑出来的8个适合新手的小项目 涉及了爬虫 多线程 selenium PhantomJs itchat 邮件发送 crontab 命令行颜色显示 excel操作 PIL 识别验证码 首先说明 天下没有免费的午餐 每个项目平均下来2元多一
  • n行Python代码系列:三行程序将提取HTML中的纯文本信息

    老猿Python博文目录 https blog csdn net LaoYuanPython article details 98245036 一 引言 最近看到好几篇类似 n行Python代码 的博文 看起来还挺不错 简洁 实用 传播了知
  • 程序员如何做副业?35岁前,千万别让死工资绊住你赚钱的步伐

    近年来互联网行情下降 好多人都在思考要不要搞个副业来抵御风险 这不又来事了 这两天又爆了互联网大裁员 继阿里 向社会输送人才 之后 京东又搞了个 毕业礼 整的小伙伴们人心惶惶 副业的关注度又一波升级 那今天我们就来聊聊 程序员做副业这件事
  • 每日一问:你想如何破坏单例模式?

    前言 1 单例是什么 单例模式 是一种创建型设计模式 目的是保证全局一个类只有一个实例对象 分为懒汉式和饿汉式 所谓懒汉式 类似于懒加载 需要的时候才会触发初始化实例对象 而饿汉式正好相反 项目启动 类加载的时候 就会创建初始化单例对象 1
  • Python基础语法学习之变量与赋值

    近几年Python飞速发展 开始学习Python的人群不在仅仅局限于编程开发者 许多其他行业的从业者也开始将Python作为自己的职业技能 本文仍然是针对零基础的初学者 继续学习Python的基础语法 变量与赋值 主要内容包括变量和赋值的概
  • python列表增加元素的三种方法

    本文主要介绍了关于python列表增加元素的几种操作方法 主要有insert方法 extend方法和append方法 每种方法给大家介绍的非常详细 希望对你有所帮助 1 insert方法 该方法包含两个参数 第一个参数为插入的位置参数 第二
  • Python编程中的for循环语句学习教程

    本文来源于公众号 csdn2299 喜欢可以关注公众号 程序员学府 这篇文章主要介绍了Python编程中的for循环语句学习教程 是Python入门学习中的基础知识 需要的朋友可以参考下 Python for循环可以遍历任何序列的项目 如一
  • python到底值不值得学,自学两年,有话说!!

    首先说说笔者自己 笔者从小就对计算机有浓厚的兴趣 无奈家里穷 买不起 考大学的时候又阴差阳错的进了文科专业 高大上的工商管理专业 第一台计算机 还是大二的时候花了600买的二手货 海尔品牌机 赛扬466cpu 那时候主流的cpu奔腾500
  • 送书|入门Python之后还是搞不定面试、做不来项目,推荐读读这本书

    又到了每周三送书的时刻啦 本周送书 Python工匠 Python 能干的事情实在太多了 掰着指头数有点不够用 Web 开发 数据分析 网络爬虫 自动化运维 后台开发 机器学习 如果你知道主攻哪个方向 只需重点去学习 不过 不论哪个方向 P

随机推荐

  • Flutter的Toast之oktoast的使用

    1 在pubspec yaml中加入 oktoast 2 0 0 然后运行package get 2 包装 app widget 在main dart中 必须使用OKToast包起来 3 调用 如果只是Toast文字 可直接调用showTo
  • 阿里云的OSS云存储的使用

    阿里云官网 https www aliyun com 通过阿里云官网 登录进入用户的界面 在搜索框中输入OSS 然后进入阿里云的对象存储OSS的控制台 未开通的开通即可 创建 Bucket 点击 Bucket 列表 查看个人的Bucket
  • 区块链:建立加密代币

    启动testrpc 打开终端 启动testrpc testrpc EthereumJS TestRPC v6 0 3 ganache core 2 0 2 代币合约的基本概念 代币合约扮演的角色相当于银行的角色 使用者在代币合约中 用自己的
  • 【Eigen 1】Eigen中的norm、normalize、normalized三者对比

    一 norm 1 对于Vector norm返回的是向量的二范数 即 x 2
  • 【vue2+element ui】添加修改共用表单的下拉框回显问题分析以及解决方案(附共用表单代码)

    目录 简介 问题复原 问题分析 共用表单代码分享 简介 本人前端水平不佳 本文分享在编写个人项目前端代码的时候遇到的回显问题的解决办法 仅供参考 问题复原 首先展示表单中的问题代码 本次前端的设计是添加和修改操作共用表单 但是其中有一个下拉
  • 陀螺产业区块链第三季

    2020年4月 国家发改委在例行新闻发布会上宣布区块链被正式列为新型基础设施中的信息基础设施 自此区块链正式搭上新基建的 风口 与传统基础设施建设相比 新型基础设施建设更加侧重于突出产业转型升级的新方向 无论是5G还是区块链 都体现出加快推
  • 网站服务器停止服务,DDoS攻击是如何让网站停止服务的?

    DDoS攻击 是一种耗尽攻击目标的系统资源 导致攻击目标无法响应正常的服务请求的网络攻击方式 虽然 大规模的DDoS攻击占据了大部分的头条新闻 但实际上 较小的DDoS攻击在网络安全环境中更为常见 在没有做好充分的防护之下 较小规模的DDo
  • 电动汽车移动充电站Mobi Charger问世

    12月26日 电动和混合动力汽车新闻网站Ecomento报道称 初创公司FreeWire针对电动汽车推出了移到充电设备Mobi Charger 目前 社会尚未认同在办公场所为电动汽车充电 举例而言 当你已经开始工作 而电动汽车正在外面充电
  • 微信小程序实现商品列表跳转详情页

    实验要求 模仿京东小程序 实现下列功能 首页包含了手机图片 手机的描述 手机的价格 购物车图标 首页显示两行文字 多余的文字隐藏 以3个点代替 点击页面不同的地方 能够跳转到不同的手机详情页面 手机详情页包含手机图片 上架日期 价格 手机描
  • centos 8 编译安装hyperscan

    一 编译安装环境配置 官方文档 http intel github io hyperscan dev reference getting started html 1 1硬件配置 配置 参数 CPU Intel Xeon Gold 5218
  • 统计学 相关性 因果_为什么相关性不表示因果关系-这种在统计中的常用说法的含义...

    统计学 相关性 因果 You might remember this simple mantra from your statistics class 您可能还记得统计课上的这个简单口头禅 Correlation does not impl
  • phpMyAdmin报错 in ./libraries/config/FormDisplay.php#661 continue targeting switch is equivalent to

    phpMyAdmin报错 in libraries config FormDisplay php 661 continue targeting switch is equivalent to break Did you mean to us
  • Android 13 媒体权限适配指南

    在 Android 系统最近的几个大版本里 更新方向有很大一部分都集中在了隐私安全这一方面 每个版本都会新增隐私安全限制 或者是对之前的隐私项进行进一步的升级 Android 10 分区存储 限制访问不可重置的硬件标识符 限制对剪贴板数据的
  • uView1.0 indexList索引列表遇到的坑

    在使用uView索引列表做通讯录的时候遇到了几个问题 先上图片 问题1 右侧的abcd首字母按钮点击错乱 比如点了f 弹出显示的是a开头的人 应该是f开头的人才对 通过排查 发现传入这个右侧组件参数的时候 后端并没有返回完整的A Z 而是有
  • C++适配器模式

    适配器模式 1 适配器模式简介 适配器模式其实是实现了两个互不兼容的已有系统之间的桥梁效果 所以适配器模式可以说是为了实现功能的一种补救措施 最好的方式是将系统重构使用工厂模式即可 但是对已有系统的重构代价过大 所以一般情况下我们都会通过适
  • 日志语义异常检测

    日志记录了软件系统运行时的详细信息 系统开发与运维人员可以根据日志监控系统剖析系统的异常行为与错误 日志异常检测可以分为语义异常 执行结果 执行异常 执行日志序列 与性能异常 执行时间 1 日志异常类型 日志记录系统在某个时间点执行了某些操
  • 设计模式-适配器模式

    文章目录 前言 介绍 实例 使用场景 优缺点 前言 当我们需要使用一个已存在的类 但其接口不符合我们的需求时 适配器模式 Adapter Pattern 可以派上用场 适配器模式是一种结构型设计模式 它允许我们创建一个中间层 将一个类的接口
  • 自己制作证件照回执

    今天身份证过期 去办理身份证 照个像回执收了30 给个6张一寸小图片 照的还不好看 因此我觉得是不是可以自己弄个回执 照片也是浪费 没有什么用 于是自己摸索了教程 1 拍一张纯色背景正面照 按照证件要求拍 手机拍照片尽量清晰 最好是相机那种
  • ReadProcessMemory Types of actual and formal var parameters must be identical

    转自 https www cnblogs com cb168 p 5884673 html delphi XE Berlin ReadProcessMemory WriteProcessMemory delphi XE Berlin dcc
  • 变长参数表va_list,模板template,打造通用函数

    假设我想写一个支持变长参数的max函数 template