首页 > 编程语言 >C++11:返回值类型后置(跟踪返回值类型)

C++11:返回值类型后置(跟踪返回值类型)

时间:2022-12-24 11:22:25浏览次数:56  
标签:11 decltype C++ return add 类型 返回值

返回值类型后置语法,是为了解决函数返回值类型依赖于参数而导致难以确定返回值类型的问题。有了这种语法以后,对返回值类型的推导就可以用清晰的方式(直接通过参数做运算)描述出来,而不需要像 C++98/03 那样使用晦涩难懂的写法。

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

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) 直接得到返回值类型即可。但是像上面这样使用十分不方便,因为外部其实并不知道参数之间应该如何运算,只有 add 函数才知道返回值应当如何推导。

那么,在 add 函数的定义上能不能直接通过 decltype 拿到返回值呢?

template <typename T, typename U>
decltype(t + u) add(T t, U u)  // error: t、u尚未定义
{
    return 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 中增加了返回类型后置(trailing-return-type,又称跟踪返回类型)语法,将 decltype 和 auto 结合起来完成返回值类型的推导。

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

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

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

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

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

如果说前一个例子中的 add 使用 C++98/03 的返回值写法还勉强可以完成,那么这个例子对于 C++ 而言就是不可能完成的任务了。在这个例子中,使用 decltype 结合返回值后置语法很容易推导出了 foo(val) 可能出现的返回值类型,并将其用到了 func 上。

标签:11,decltype,C++,return,add,类型,返回值
From: https://www.cnblogs.com/crossoverpptx/p/17002506.html

相关文章

  • 洛谷P1196 [NOI2002] 银河英雄传说
    slojP2577.食物链题目大意一个序列初始编号为1,2,3,,,30000有2个操作:mij合并第i列和第j列,将第i列头部接到第j列尾部cIj询问i号和j号之间的数量,若......
  • POJ 1159 Palindrome
    POJ1159Palindrome题意:给出一个字符串,求最少插入多少个字符可以让该字符串变成回文字符串思路1:思路1是卡过去的(用\(short\)换\(int\)和用了一个常数优化),所......
  • C++进阶(哈希)
    vector容器补充(下面会用到)我们都知道vector容器不同于数组,能够进行动态扩容,其底层原理:所谓动态扩容,并不是在原空间之后接续新空间,因为无法保证原空间之后尚有可配置的空间......
  • C++——贪心
     5745:演讲大厅安排描述有一个演讲大厅需要我们管理,演讲者们事先定好了需要演讲的起始时间和中止时间。我们想让演讲大厅得到最大可能的使用。我们要接受一些预定而拒......
  • C++读写文本文件
    std::stringreadText(std::string&filename){std::stringshaderCodeStr("");std::ifstreamshaderFile;shaderFile.exceptions(std::ifstream::failb......
  • 省选11. 字符串
    P3426[POI2005]SZA-Template考虑dp,设\(f(i)\)表示前\(i\)字符所需要的最小印章。\(f(i)\)要么等于\(i\),要么等于\(f(nxt(i))\)。如果存在\(j\geqn-nxt(i)\),......
  • win11的常用设置
    win11休眠按钮显示win11右键显示风格注:以下操作是将win11风格改为win10风格。打开注册表编辑器,定位到HKEY_CURRENT_USER\SOFTWARE\CLASSES\CLSID;右键点击CLSID键......
  • AcWing1131. 拯救大兵瑞恩
    题目传送门解题思路\(\qquad\)我们可以用一个状态压缩的思路,对于所有的钥匙,用来开第\(i\)类门的我们把这把钥匙放到从右往左数的第\(i\)位(这里是为了方便写,比如开第\(1\)......
  • POJ 1163 The Trangle
    POJ1163TheTrangle题意:给出一个数字三角形,每个分叉路口可以选择一条道路向下走,获得路上的点的权值。求可以获得的最大权值是多少?定义状态:我们需要知道当每个位置......
  • C++Primer
    第2章2.1基本内置类型1、表示整数、字符和布尔值的算术类型合称为**整型**2、0值算术类型代表false,任何非0的值都代表true3、在一行末尾加“\”,可将此行和下一行当......