当前位置:首页 > 科技  > 软件

C++函数模板:掌握返回类型推导的艺术

来源: 责编: 时间:2024-01-18 09:41:15 163观看
导读编译器推导返回类型讨论 add() 函数模板的示例,让编译器推导返回值的类型确实是个好主意。然而,返回类型依赖于模板类型参数,那该如何实现呢?例如,考虑以下函数模板:template <typename T1, typename T2>RetType add(const

编译器推导返回类型

讨论 add() 函数模板的示例,让编译器推导返回值的类型确实是个好主意。然而,返回类型依赖于模板类型参数,那该如何实现呢?例如,考虑以下函数模板:56z28资讯网——每日最新资讯28at.com

template <typename T1, typename T2>RetType add(const T1& t1, const T2& t2) {    return t1 + t2;}

在这个示例中,RetType 应该是表达式 t1 + t2 的类型,但你无法知道这一点,因为你不知道 T1 和 T2 是什么。56z28资讯网——每日最新资讯28at.com

56z28资讯网——每日最新资讯28at.com

自动类型推导

自 C++14 起,你可以让编译器自动推导函数的返回类型。因此,你可以简单地将 add() 写成如下:56z28资讯网——每日最新资讯28at.com

template <typename T1, typename T2>auto add(const T1& t1, const T2& t2) {    return t1 + t2;}

在 C++ 中,当使用 auto 关键字来推导函数返回值的类型时,它会自动去除表达式中的引用(reference)和 const 限定符。这意味着,如果函数的返回类型原本是一个引用或 const 类型,使用 auto 推导后,返回值将会失去这些属性。例如,如果原本返回的是一个 const 引用,使用 auto 推导后,返回值将仅是一个值,而非引用,并且也不再是 const 类型。56z28资讯网——每日最新资讯28at.com

对于某些函数来说,这种去除引用和 const 的行为是可以接受的。例如,在 add() 函数模板中,如果使用 auto,这通常没问题,因为 operator+(加法运算符)一般返回一个新的对象,而不是引用或 const 对象。56z28资讯网——每日最新资讯28at.com

然而,在其他一些情况下,可能需要保留函数返回值的原始属性,比如其为引用或 const 类型。在这些情况下,简单地使用 auto 来推导返回类型可能就不够理想了。因此,需要使用其他方法(使用 decltype(auto) 的函数模板)来确保函数返回值的原始属性被正确保留。56z28资讯网——每日最新资讯28at.com

auto 与 decltype 的区别

考虑以下非模板示例,了解 auto 和 decltype 之间的差异:56z28资讯网——每日最新资讯28at.com

const std::string message { "Test" };const std::string& getString() { return message; }auto s1 { getString() }; // s1 是 string 类型,进行了拷贝const auto& s2 { getString() }; // s2 是对常量的引用decltype(getString()) s3 { getString() }; // s3 是 const string& 类型decltype(auto) s4 { getString() }; // s4 也是 const string& 类型

使用 decltype(auto) 的函数模板

有了这些知识,我们可以使用 decltype(auto) 来编写我们的 add() 函数模板,以避免去除任何 const 和引用限定符:56z28资讯网——每日最新资讯28at.com

template <typename T1, typename T2>decltype(auto) add(const T1& t1, const T2& t2) {    return t1 + t2;}

C++14 之前的方法

在 C++14 之前,也就是在函数返回类型推导和 decltype(auto) 得到支持之前,问题是通过使用 decltype(expression) 来解决的,这是 C++11 引入的。例如,你可能会写出以下代码:56z28资讯网——每日最新资讯28at.com

template <typename T1, typename T2>decltype(t1 + t2) add(const T1& t1, const T2& t2) {    return t1 + t2;}

然而,这是错误的。你在原型行的开头使用了 t1 和 t2,但这些参数还未知。t1 和 t2 在到达参数列表末尾时才变得已知。56z28资讯网——每日最新资讯28at.com

这个问题曾经通过替代函数语法解决。注意,在这种语法中,auto 用于原型行的开头,而实际的返回类型在参数列表之后指定(尾随返回类型);因此,参数的56z28资讯网——每日最新资讯28at.com

名称(以及它们的类型,从而 t1 + t2 的类型)是已知的:56z28资讯网——每日最新资讯28at.com

template<typename T1, typename T2>auto add(const T1& t1, const T2& t2) -> decltype(t1 + t2) {    return t1 + t2;}

注意:现在 C++ 支持 auto 返回类型推导和 decltype(auto),建议使用这些机制,而不是替代函数语法。56z28资讯网——每日最新资讯28at.com

56z28资讯网——每日最新资讯28at.com

C++20 的新特性

C++20 引入了一种简化的函数模板语法。再次回顾前面的 add() 函数模板。这里是推荐的版本:56z28资讯网——每日最新资讯28at.com

template <typename T1, typename T2>decltype(auto) add(const T1& t1, const T2& t2) {    return t1 + t2;}

看这个示例,为了指定一个简单的函数模板,语法显得相当冗长。使用简化的函数模板语法,可以更优雅地写成如下:56z28资讯网——每日最新资讯28at.com

decltype(auto) add(const auto& t1, const auto& t2) {    return t1 + t2;}

使用这种语法,不再需要 template<> 规范来指定模板参数。相反,以前在实现中使用的 T1 和 T2 类型现在被指定为 auto。这种简化的语法只是语法糖;编译器会自动将这种简化实现转换为更长的原始代码。基本上,每个被指定为 auto 的函数参数都成为一个模板类型参数。56z28资讯网——每日最新资讯28at.com

需要注意的两个问题

(1) 不同的模板类型参数:每个被指定为auto的参数都成为不同的模板类型参数。假设你有这样一个函数模板:56z28资讯网——每日最新资讯28at.com

template <typename T>decltype(auto) add(const T& t1, const T& t2) {    return t1 + t2;}

这个版本只有一个模板类型参数,而函数的两个参数 t1 和 t2 都是 const T& 类型。对于这样的函数模板,你不能使用简化语法,因为这将被转换为具有两个不同模板类型参数的函数模板。56z28资讯网——每日最新资讯28at.com

(2) 无法显式使用推导类型:你不能在函数模板的实现中显式使用这些自动推导的类型,因为这些自动推导的类型没有名称。如果你需要这样做,你要么需要继续使用普通的函数模板语法,要么使用 decltype() 来确定类型。56z28资讯网——每日最新资讯28at.com

// C++50 中的 auto 使用auto auto(auto... args) {    return (... + args);}

本文链接:http://www.28at.com/showinfo-26-64104-0.htmlC++函数模板:掌握返回类型推导的艺术

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 2024年不容错过的十个开发框架

下一篇: 微服务和无服务器架构时代的持续测试

标签:
  • 热门焦点
  • 鸿蒙OS 4.0公测机型公布:甚至连nova6都支持

    鸿蒙OS 4.0公测机型公布:甚至连nova6都支持

    华为全新的HarmonyOS 4.0操作系统将于今天下午正式登场,官方在发布会之前也已经正式给出了可升级的机型产品,这意味着这些机型会率先支持升级享用。这次的HarmonyOS 4.0支持
  • 企业采用CRM系统的11个好处

    企业采用CRM系统的11个好处

    客户关系管理(CRM)软件可以为企业提供很多的好处,从客户保留到提高生产力。  CRM软件用于企业收集客户互动,以改善客户体验和满意度。  CRM软件市场规模如今超过580
  • 如何使用JavaScript创建一只图像放大镜?

    如何使用JavaScript创建一只图像放大镜?

    译者 | 布加迪审校 | 重楼如果您曾经浏览过购物网站,可能遇到过图像放大功能。它可以让您放大图像的特定区域,以便浏览。结合这个小小的重要功能可以大大改善您网站的用户体验
  • 梁柱接棒两年,腾讯音乐闯出新路子

    梁柱接棒两年,腾讯音乐闯出新路子

    文丨田静 出品丨牛刀财经(niudaocaijing)7月5日,企鹅FM发布官方公告称由于业务调整,将于9月6日正式停止运营,这意味着腾讯音乐长音频业务走向消亡。腾讯在长音频领域还在摸索。为
  • 10天营收超1亿美元,《星铁》比《原神》差在哪?

    10天营收超1亿美元,《星铁》比《原神》差在哪?

    来源:伯虎财经作者:陈平安即便你没玩过《原神》,你一定听说过的它的大名。恨它的人把《原神》开服那天称作是中国游戏史上最黑暗的一天,有粉丝因为索尼在PS平台上线《原神》,怒而
  • 新电商三兄弟,“抖快红”成团!

    新电商三兄弟,“抖快红”成团!

    来源:价值研究所作 者:Hernanderz 随着内容电商的概念兴起,抖音、快手、小红书组成的&ldquo;新电商三兄弟&rdquo;成为业内一股不可忽视的势力,给阿里、京东、拼多多带去了巨大压
  • 东方甄选单飞:有些鸟注定是关不住的

    东方甄选单飞:有些鸟注定是关不住的

    作者:彭宽鸿来源:华尔街科技眼&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;东方甄选创始人俞敏洪带队的&ldquo;7天甘肃行&rdquo;直播活动已在近日顺利收官。成立后一
  • iQOO Neo8 Pro评测:旗舰双芯加持 最强性能游戏旗舰

    iQOO Neo8 Pro评测:旗舰双芯加持 最强性能游戏旗舰

    【Techweb评测】去年10月,iQOO推出了一款Neo7手机,该机搭载了联发科天玑9000+,配备独显芯片Pro+,带来了同价位段最佳的游戏体验,一经上市便受到了诸多用
  • 联想的ThinkBook Plus下一版曝光,键盘旁边塞个平板

    联想的ThinkBook Plus下一版曝光,键盘旁边塞个平板

    ThinkBook Plus 是联想的一个特殊笔记本类别,它在封面放入了一块墨水屏,也给人留下了较为深刻的印象。据有人爆料,联想的下一款 ThinkBook Plus 可能更特殊,它
Top