C++14尝鲜:函数返回类型自动推导

2023-11-06

函数返回类型自动推导

函数返回类型自动推导是指C++11以及C++14中不直接给出函数返回类型,而是使用类型指示符来指示返回类型甚至彻底省略返回类型并最终由编译器来推导返回类型的语言特性。
函数返回类型自动推导原则如下:

  • 当函数体内不包含任何返回值时,该函数的返回类型为void。
  • 当函数体内只包含一句带返回值的return语句时,该函数的返回类型等同于该返回值的类型。
  • 当函数体内包含多个带返回值的return语句时,该函数的返回类型由这些返回值的类型共同决定,所有返回值的类型必须相同。
  • 函数体内的返回值可以递归调用自身,但这类无法由编译器自动推导类型的返回值,必须发生在可以由编译器自动推导类型的非递归调用的返回值之后。

在lambda表达式中省略返回类型

当lambda表达式中省略返回类型时,lambda表达式的返回类型由编译器根据返回值以及模板参数推导规则进行自动推导。

声明函数时使用auto指示符来指示返回类型

当函数的返回类型包含auto指示符并且函数的后置返回类型被省略时,函数的返回类型由编译器根据返回值以及模板参数推导规则进行自动推导。

声明函数时使用decltype(auto)指示符来指示返回类型

当函数的返回类型为decltype(auto)指示符时,函数的返回类型由编译器根据返回值以及decltype推导规则进行自动推导。

#include <iostream>
#include <string>
#include <typeinfo>

template<typename T>  
T f();

auto f2(int n)
{
    return n + 1;
}
auto f3(bool b)
{
    if(b) return 1.0;
    else return 2.0;
}
auto f4(int n)
{
    if(n == 0) return 1;
    else return n * f4(n - 1);
}
struct S
{
    int n1, n2;
    decltype(auto) f6(bool b)
    {
        if(b) return (n1);
        else return (n2);
    }
};

int main()
{
    auto f1 = [](int a){std::cout << a;};
    auto f5 = [](auto a, auto b){return a + b;};
    f<decltype(f1(1))>();
    f<decltype(f2(1))>();
    f<decltype(f3(false))>();
    f<decltype(f4(3))>();
    f<decltype(f5(1.0f, 3.0f))>();
    S s;
    f<decltype(s.f6(false))>();
}
main.cpp:(.text.startup+0x5): undefined reference to `void f<void>()'
main.cpp:(.text.startup+0xa): undefined reference to `int f<int>()'
main.cpp:(.text.startup+0xf): undefined reference to `double f<double>()'
main.cpp:(.text.startup+0x14): undefined reference to `int f<int>()'
main.cpp:(.text.startup+0x19): undefined reference to `float f<float>()'
main.cpp:(.text.startup+0x1e): undefined reference to `int& f<int&>()'

这段代码使用了一种特殊技巧来查看编译器所实际推导出的函数返回类型。代码中定义了一个未被实现的函数模板f,该函数模板有一个类型参数T。如果用某个类型T来调用该函数模板,编译器就会因找不到函数模板的定义而输出”T f<T>()未被定义“的出错信息。也就是说,利用该函数模板,我们便可以在编译器所输出的出错信息中检查模板参数T的实际类型。在main函数内,我们充分利用了这一个技巧,通过利用函数返回类型调用该函数模板来让编译器输出相应的类型。
从出错信息中可以得知:

  • lambda表达式f1的返回类型被推导为void。
    理由:lambda表达式的函数体内没有任何返回值。
  • 函数f2的返回类型被推导为int。
    理由:函数体内只包含一个return语句,返回值n+1类型为int。
  • 函数f3的返回类型被推导为double。
    理由:函数体内包含两个return语句,返回值1.0以及2.0类型都是double。
  • 函数f4的返回类型被推导为int。
    理由:函数体内包含两个return语句,其中第二个返回值递归调用自身,无法推导,而第一个返回值1类型为int。
  • lambda表达式f5的返回类型被推导为表达式a+b的类型。当 a=1.0f, b=3.0f 时,f5的返回类型为表达式 1.0f + 3.0f 的类型,即float。
    理由:函数体内只包含一个return语句,返回值a+b类型取决于泛型参数a以及b的类型。
  • 函数f6的返回类型被推导为int&。
    理由:函数体内包含两个return语句,将返回值(n1)以及(n2)代入decltype(auto)结果类型都是int&。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++14尝鲜:函数返回类型自动推导 的相关文章

  • 使用 CLion 进行 OpenCV Windows 设置

    我想在 Windows 上为 CLion IDE 设置 OpenCV 我尝试使用 OpenCV 3 1 和 2 4 得到相同的结果 我有 Windows 10 64 位 CLion 使用 cygwin 环境 到目前为止我做了什么 1 从Op
  • 您可以从基本 Win32 控制台模板应用程序中的 C#/Winrt 组件调用(不是 WinForm/abstractions/wrappers 或使用 C++/Winrt 模板)吗?)

    我有一个现有的程序 win32 x86 控制台应用程序 需要调用托管代码 来自 Net 的 C dll The dll不暴露给 COM 但可以从 C WinRT 组件调用并由 C WinRT 控制台模板应用引用 BUT即使安装了 C Win
  • 检测wlan是否关闭

    任何人都可以给我一个提示 如何在 Windows Phone 上以编程方式检测 C 8 1 应用程序 不是 8 0 是否启用 禁用 WLAN 我不想更改这些设置 只是需要知道 该解决方案是一个 Windows 8 1 通用应用程序 Wind
  • 将完整模板参数值映射到原始类型

    我想将数字映射到类型 在这个例子中 我将创建一个函数 将 sizeof 结果映射到有符号的原始类型 我想知道是否有更好的方法来完成我在现代 C 中所做的事情 即采用模板化值并将其转换为类型 现在 这可以将大小转换为已知类型 但我似乎无法在标
  • CSharpRepl emacs 集成?

    我碰巧知道莫诺CSharpRepl http www mono project com CsharpRepl 是否有 emacs csharp 模式使用它在一个窗口中运行 REPL 并像 python 模式一样在另一个窗口中编译 运行 C
  • 运行需要 MySql.Data 的内置 .NET 应用程序

    我在运行我编写的内置 NET 应用程序时遇到问题 我的应用程序使用最新的 MySql 连接器 该连接器安装在我的系统上 当我尝试将其添加为引用时 该连接器显示为 NET 4 Framwork 组件 当我在环境中以调试模式运行应用程序时 一切
  • 检测到堆栈崩溃

    我正在执行我的 a out 文件 执行后 程序运行一段时间 然后退出并显示消息 stack smashing detected a out terminated Backtrace lib tls i686 cmov libc so 6 f
  • Gwan C#,如何获取HTTP标头?

    我需要它来重写 url 以了解我正在处理哪个友好的 url 用于用户代理和其他东西 EDIT public class Gwan MethodImplAttribute MethodImplOptions InternalCall exte
  • 如何制作可启动程序?

    所以 这个问题可能看起来很奇怪 但假设我编译了 int main void int x 3 int y 4 int z x y 是否可以让CPU这样运行 如何 例如 这允许我写入监视器吗 如果我没记错的话 内存中有些地方可以写入要显示的内容
  • 为什么'enable_if'不能用于禁用这里声明

    include
  • 使用 LINQ 更新 IEnumerable 对象的简单方法

    假设我有一个这样的业务对象 class Employee public string name public int id public string desgination public int grade List
  • 访问 ascx 文件中的母版页控件

    我有一个母版页文件 其中包含 2 个面板控件中的 2 个菜单 我还使用控件来检查用户是否登录并获取用户类型 根据我想要显示 隐藏面板的类型 控件本身不在母版页中引用 而是通过 CMS 系统动态引用 我想在用户控件中使用findcontrol
  • 使用查询表达式对 List 进行排序

    我在使用 Linq 订购这样的结构时遇到问题 public class Person public int ID get set public List
  • MFC:如何设置CEdit框的焦点?

    我正在开发我的第一个简单的 MFC 项目 但我正在努力解决一个问题 想要设置所有的焦点CEdit其中一个对话框中的框 我的想法是 当打开对话框时 焦点位于第一个编辑框上 然后使用 选项卡 在它们之间交换 我看到了方法SetFocus 但我无
  • 如何对 NServiceBus.Configure.WithWeb() 进行单元测试?

    我正在构建一个 WCF 服务 该服务接收外部 IP 上的请求并将其转换为通过 NServiceBus 发送的消息 我的单元测试之一调用Global Application Start 它执行应用程序的配置 然后尝试将 Web 服务解析为 验
  • 搜索实体的所有字段

    我正在尝试在客户数据库上实现 多功能框 类型的搜索 其中单个查询应尝试匹配客户的任何属性 这是一些示例数据来说明我想要实现的目标 FirstName LastName PhoneNumber ZipCode Mary Jane 12345
  • 使用具有抗锯齿功能的 C# 更改抗锯齿图像的背景颜色

    我有一个图像需要更改背景颜色 例如 将下面示例图像的背景更改为蓝色 然而 图像是抗锯齿的 所以我不能简单地用不同的颜色替换背景颜色 我尝试过的一种方法是创建第二个图像 仅作为背景 并更改其颜色并将两个图像合并为一个图像 但是这不起作用 因为
  • 为什么以下 C 程序会出现总线错误?

    我认为这是第一个失败的 strtok 调用 好久没写C了 有点不知所措 非常感谢 include
  • 如何得知客户端从服务器的下载速度?

    根据客户的下载速度 我想以低质量或高质量显示视频 任何 Javascript 或 C 解决方案都是可以接受的 Thanks 没有任何办法可以确定 您只能测量向客户端发送数据的速度 如果没有来自客户端的任何类型的输入来表明其获取信息的速度 您
  • 来自 3rd 方库的链接器错误 LNK2019

    我正在将旧的 vc 6 0 应用程序移植到 vs2005 我收到以下链接器错误 我花了几天时间试图找到解决方案 错误LNK2019 无法解析的外部符号 imp 创建AwnService 52 在函数 public int thiscall

随机推荐