C++11返回类型后置语法的使用示例

C++11新标准增加的auto不仅可以自动推断变量类型,还能结合decltype来表示函数的返回值。这些新特性可以让我们写出更简洁、更现代的代码。

在泛型编程中,可能需要通过参数的运算来得到返回值的类型。

我们看一下下面这个例子:

#include<iostream>
using namespace std;

template <typename R,typename T, typename U>
R add(T t,U u)
{
  return t+u;
}

int main()
{
  int a=1;
  float b=2.0;
  auto c = add<decltype(a+b)>(a,b);
}

我们并不关心a+b类型是什么,因为,只需要通过decltype(a+b)直接得到返回值类型即可。但像上面这样使用十分不方便,因为外部其实并不知道参数之间应该如何运算,只有add函数才知道返回值应当如何推导。

那么我们可不可以直接在函数定义上通过decltype拿到返回值呢?比如像这样:

template <typename T, typename U>
decltype(t+u) add(T t,U u)      //编译错误,t,u未定义
{
  return t+u;
}

运行后,编译器会提示错误,告诉我们decltype(t+u)中t和u在此作用域中尚未声明。

因为t、u在参数列表中,而C++的返回值是前置语法,在返回值定义的时候参数变量还不存在。

对于本例子,可行的写法如下:

template <typename T, typename U>
decltype(T()+U()) add(T t,U u)
{
  return t+u;
}

考虑到T、U可能是没有无参构造函数的类,正确的写法应该是这样:

template <typename T, typename U>
decltype((*(T*)0)+(*(U*)0)) add(T t,U u)
{
  return t+u;
}

虽然成功地使用decltype完成了返回值的推导,但写法过于晦涩,会大大增加decltype在返回值类型推导上的使用难度并降低了代码的可读性。

因此,在C++11中增加了返回类型后置语法,将decltype和auto结合起来完成返回值类型的推导。

返回类型后置语法是通过auto和decltype结合起来使用的。上面的add函数,使用新的语法可以写成:

template <typename T, typename U>
auto add(T t,U u) ->decltype(t+u)
{
  return t+u;
}

为了进一步说明这个语法,再看另一个例子:

#include<iostream>
using namespace std;

int& foo(int& i);
float foo(float& f);

template <typename T>
auto func(T& val) -> decltype(foo(val))
{
  return foo(val);
}

在这个例子中,使用decltype结合返回值后置语法很容易推导出了foo(val)可能出现的返回值类型,并将其用到了func上。

返回值类型后置语法,是为了解决函数返回值类型依赖于参数而导致难以确定返回值类型的问题。有了这种语法以后,对返回值类型的推导就可以用清晰的方式描述出来。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 用C++实现strcpy(),返回一个char*类型的深入分析

    代码如下所示: 复制代码 代码如下: #include "stdafx.h"#include <string>#include <iostream>using namespace std;char* strcpy(char *src_str, char *dest_str){ char* dest = dest_str; if ((src_str == NULL)||(dest_str == NULL))  //检查指针有效性 {  throw "In

  • C++11返回类型后置语法的使用示例

    C++11新标准增加的auto不仅可以自动推断变量类型,还能结合decltype来表示函数的返回值.这些新特性可以让我们写出更简洁.更现代的代码. 在泛型编程中,可能需要通过参数的运算来得到返回值的类型. 我们看一下下面这个例子: #include<iostream> using namespace std; template <typename R,typename T, typename U> R add(T t,U u) { return t+u; } int main()

  • C++返回值类型后置实现(跟踪返回值类型)

    在泛型编程中,可能需要通过参数的运算来得到返回值的类型.考虑下面这个场景: template <typename R, typename T, typename U> R add(T t, U u) { return t+u; } int a = 1; float b = 2.0; auto c = add<decltype(a + b)>(a, b); 我们并不关心 a+b 的类型是什么,因此,只需要通过 decltype(a+b) 直接得到返回值类型即可.但是像上面这样使用十分

  • SpringMVC修改返回值类型后的消息转换器处理方式

    目录 问题案例 为什么? 了解问题原因及分析 解决方法 结语 o(╯□╰)o这标题看起来有点奇怪,所以先以一个小小的案例来说明一下本文要描述和解决的问题 问题案例 假设有一个Controller方法如下 @RequestMapping(value = "test") @ResponseBody public Object test() { Map<String,String> param = new HashMap<>(); param.put("na

  • Python序列对象与String类型内置方法详解

    本文实例讲述了Python序列对象与String类型内置方法.分享给大家供大家参考,具体如下: 前言 在Python数据结构篇中介绍了Python的序列类型数据结构,这次继续深入的学习序列和String类型对象的内建方法. 软件环境 系统 UbuntuKylin 14.04 软件 Python 2.7.3 IPython 4.0.0 序列类型 序列类型,即由整数进行索引的对象的有序集合.其中又可以分为下面两类: 可变序列:列表,支持元素的插入.删除.替换 不可变序列:元组.字符串 序列的操作方法

  • 11个Python3字典内置方法大全与示例汇总

    概述 在绝大部分的开发语言中与实际开发过程中,Dictionary扮演着举足轻重的角色.从我们的数据模型到服务器返回的参数到数据库的应用等等,Dictionary的身影无处不在. 在Python中,Dictionary是一种可变的容器类型.所谓容器类型,就是我们放置数据的地方.不同于List的有序.操作时对数据类型统一性的要求较严格,Dictionary是一种可变的.不限存储对象.无序的数据模型. 字典有着类似列表的高灵活度的特点,而与列表通过偏移索引的存取元素的方式不同,字典是通过无序的键来存

  • 详解C++11原子类型与原子操作

    1.认识原子操作 原子操作就是在多线程程序中"最小的且不可并行化的"操作,意味着多个线程访问同一个资源时,有且仅有一个线程能对资源进行操作.通常情况下原子操作可以通过互斥的访问方式来保证,例如Linux下的互斥锁(mutex),Windows下的临界区(Critical Section)等.下面看一个Linux环境使用POSIX标准的pthread库实现多线程下的原子操作: #include <pthread.h> #include <iostream> usi

  • Spring BeanPostProcessor(后置处理器)的用法

    目录 BeanPostProcessor 一.自定义后置处理器演示 二.多个后置处理器 三.显示指定顺序 对BeanPostProcessor接口的理解 为了弄清楚Spring框架,我们需要分别弄清楚相关核心接口的作用,本文来介绍下BeanPostProcessor接口 BeanPostProcessor 该接口我们也叫后置处理器,作用是在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑.注意是Bean实例化完毕后及依赖注入完成后触发的.接口的源码如下 publ

  • Java 图解Spring启动时的后置处理器工作流程是怎样的

    探究Spring的后置处理器 本次我们主要探究invokeBeanFactoryPostProcessors():后面的代码下次再做解析: 入口代码refresh() AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); // ...... applicationContext.refresh(); public void refresh() throws

  • ThinkPHP6.0前置、后置中间件区别

    目录 1. 创建中间件 2. 注册中间件 3. 前置.后置中间件 4. 前置.后置中间件的区别 5. 后置中间件登录拦截器(不推荐) 6. 前置中间件登录拦截器(推荐使用) 1. 创建中间件 命令行创建中间件类文件示例 // app\middleware\Auth php think make:middleware Auth // app\middleware\admin\Auth php think make:middleware admin/Auth // app\admin\middlew

  • C++中操作符的前置与后置有什么区别

    目录 一.值得思考的问题 二.意想不到的事实 三.++ 操作符重载 四.真正的区别 五.小结 一.值得思考的问题 下面的代码有没有区别?为什么? 二.意想不到的事实 现代编译器产品会对代码进行优化 优化使得最终的二进制程序更加高效 优化后的二进制程序丢失了 C/C++ 的原生语义 不可能从编译后的二进制程序还原 C/C++ 程序 三.++ 操作符重载 ++ 操作符可以重载吗?如何区分前置++ 和后置++? ++ 操作符可以被重载 全局函数和成员函数均可进行重载 重载前置++操作符不需要额外的参数

随机推荐