1. decltype 的作用

decltype 是C++11引入的一个关键字,用来推断表达式的类型。它返回的是表达式的精确类型,包括引用和const限定符等。

例子:

int x = 5;
decltype(x) y = x; // y 的类型是 int

在这个例子中,decltype(x)返回 int,因为 x 是一个 int 类型的变量,所以 y 的类型也被推导为 int

更复杂的例子:

const int& z = x;
decltype(z) w = z; // w 的类型是 const int&

在这里,decltype(z)返回的是 const int&,因为 z 是一个常量引用。

2. std::decay_t 的作用

std::decay_t 是 C++14 中引入的一个类型转换工具,它基于 std::decay,用于将某种类型转换为“衰变”后的类型。衰变的过程涉及以下几种转换:

  1. 如果是数组类型,衰变为指针类型。
  2. 如果是函数类型,衰变为指针类型。
  3. 如果是引用类型,去除引用。
  4. 去除 constvolatile 限定符。

std::decay_t<T> 其实等价于 typename std::decay<T>::type,但使用起来更加简洁。

例子:

int arr[10];
std::decay_t<decltype(arr)> ptr; // ptr 的类型为 int*

在这个例子中,arr 是一个数组类型 int[10],而 std::decay_t<decltype(arr)> 将其类型推导并转换为指针 int*

std::decay_tdecltype 一起使用

std::decay_tdecltype 可以结合使用,特别是在模板编程中,当我们需要对某个表达式进行推断并获得其标准化(即衰变)后的类型时非常有用。

例子:

int arr[5] = {1, 2, 3, 4, 5};
std::decay_t<decltype(arr)> p = arr; // p 的类型是 int*,而不是 int[5]

decltype(arr) 返回 int[5],但是通过 std::decay_t,我们把这个类型衰变成了 int*,从而使 p 成为一个指向数组的指针。

3. C++中的其他类型推断工具

C++11及以后版本引入了许多类型推断机制,下面介绍一些常用的:

3.1 auto

auto 是C++11引入的关键字,用于自动推断变量的类型。编译器通过变量的初始化表达式推断出具体的类型。

例子:

int x = 10;
auto y = x; // y 的类型为 int

对于较为复杂的表达式,auto 仍然可以推断出正确的类型:

std::vector<int> vec = {1, 2, 3};
auto it = vec.begin(); // it 的类型为 std::vector<int>::iterator

3.2 decltype(auto)

decltype(auto) 是 C++14 引入的,它结合了 autodecltype 的特性。

decltype(auto) 会精确推导出表达式的类型,包括constvolatile和引用修饰符。

例子:

int x = 10;
int& foo() { return x; } decltype(auto) y = foo(); // y 的类型为 int&

在这个例子中,decltype(auto) 会推导出 foo() 的返回类型 int&,所以 y 是一个引用。如果使用普通的 autoy 则会是 int 类型(去掉了引用)。

3.3 std::forwardstd::declval

  • std::forward<T>:主要用于保持模板函数中参数的左右值属性,用于完美转发(perfect forwarding)。

    例子:

    template<typename T>
    void wrapper(T&& arg) {
    process(std::forward<T>(arg)); // 保持传入参数的左右值特性
    }
  • std::declval<T>:用于获取某个类型的右值引用,而无需实际创建该类型的实例。通常用于不能默认构造的类型中推导出其返回类型。

    例子:

    template<typename T>
    auto getReturnType() -> decltype(std::declval<T>().someFunction()) {
    // 这里不需要实际构造 T 对象,只是用于推导返回类型
    }

3.4 trailing return type

C++11引入了一种新的返回类型语法,称为尾随返回类型(trailing return type),它结合了 decltype 来推导函数的返回类型。

例子:

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

在这个例子中,decltype(a + b) 通过表达式 a + b 推导出返回类型。这在函数模板中非常有用,尤其是当返回类型依赖于模板参数的运算时。

4. 总结

  • decltype:用于推断表达式的精确类型,保留引用和const等限定符。
  • std::decay_t:将类型进行标准化衰变,移除引用、const 和数组类型等特性。
  • auto:用于根据初始化表达式自动推断变量类型。
  • decltype(auto):结合decltypeauto的特性,能够精确推导类型。
  • std::forward:用于完美转发,保持参数的左右值属性。
  • std::declval:用于推导无法直接实例化的类型的表达式类型。

C++中的类型推断机制的更多相关文章

  1. Java泛型中的类型擦除机制简单理解

    Java的泛型是JDK1.5时引入的.下面只是简单的介绍,不做深入的分析. Java的泛型是伪泛型.为什么说Java的泛型是伪泛型呢?因为,在编译期间,所有的泛型信息都会被擦除掉.正确理解泛型概念的首 ...

  2. Attr类中进行类型推断

    涉及到重要的类的继承关系如下图所示. 关于抛出的异常继承体系:

  3. C#的类型推断发展史

    前言:随着C#的版本升级,C#编译器的类型推断功能也在不断的升级以适应语言进化过程中的变化,并为这个过程做了相应的优化. 隐式类型的数组 在C#1和C#2中,作为变量声明和初始化的一部分,初始化数组的 ...

  4. TypeScript Type Innference(类型推断)

    在这一节,我们将介绍TypeScript中的类型推断.我们将会讨论类型推断需要在何处用到以及如何推断. 基础 在TypeScript中,在几个没有明确指定类型注释的地方将会使用类型推断来提供类型信息. ...

  5. WebKit Web Inspector增加覆盖率分析和类型推断功能

    WebKit中的Web Inspector(Web检查器)主要用于查看页面源代码.实时DOM层次结构.脚本调试.数据收集等,日前增加了两个十分有用的新功能:覆盖率分析和类型推断.覆盖率分析工具能够可视 ...

  6. 聊聊 TypeScript 中的类型保护

    聊聊 TypeScript 中的类型保护 在 TypeScript 中使用联合类型时,往往会碰到这种尴尬的情况: interface Bird { // 独有方法 fly(); // 共有方法 lay ...

  7. Lambda 表达式(使用前提、“类型推断”、作用、优缺点、Lambda还能省略的情况)

    Lambda 表达式(使用前提."类型推断".作用.优缺点.Lambda还能省略的情况) 1.Lambda使用前提: (1)使用Lambda必须有接口,且接口只有一个抽象方法(即函 ...

  8. 推断js中的类型:typeof / instanceof / constructor / prototype

    怎样推断js中的类型呢,先举几个样例: var a = "jason"; var b = 123; var c = true; var d = [1,2,3]; var e = n ...

  9. java8中对lamdba表达式方法参数传递时,方法重载之后的类型推断

    java8中可以向方法传递一个lamdba表达式,今天看书关于类型推断碰到一个问题: 这个问题我实际操作了一下:得出结论 如果是只有一个方法的情况下,方法参数使用lamdba表达式的时候是不需要写类型 ...

  10. C#中的常量、类型推断和作用域

    一.常量 常量是其值在使用过程中不会发生变化的变量.在声明和初始化变量时,在变量前面家关键字const,就可以把该变量指定为一个常量: const int a=100;//a的值将不可以改变 常量的特 ...

随机推荐

  1. AppiumDesktop控制手机和安卓模拟器

    前言: 本期内容 如何用AppiumDesktop连接安卓手机和安卓模拟器 AppiumDesktop基本参数的获取方法,及如何驱动安卓设备 AppiumDesktop在模拟登陆和爬虫中用到的基本功能 ...

  2. scratch编程作品-《滚动的物理小球》

    程序说明: <滚动的物理小球>是一款基于Scratch平台开发的小游戏.在这个游戏中,玩家通过按左右方向键来控制一个小球在屏幕上的左右移动.小球在移动过程中,完全遵循物理引擎的规则,如加速 ...

  3. 如何通过PowerShell批量修改O365用户的office phone属性值

    我的博客园:https://www.cnblogs.com/CQman/ 如何通过PowerShell批量修改O365用户的office phone属性值? 需求信息: 组织中的O365用户在创建时, ...

  4. vue里使用px2rem

    安装 yarn add postcss-px2rem 配置 在vue.config.js中添加以下配置 const px2rem = require('postcss-px2rem') module. ...

  5. OpenCV计算机视觉学习(16)——仿射变换学习笔记

    如果需要其他图像处理的文章及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractic ...

  6. 【转载】ubuntu用户/linux用户登录后没有自动加载.bashrc

    版权声明:本文为CSDN博主「安安爸Chris」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog.csdn.net/mimiduc ...

  7. 【转载】AI的剥削:肯尼亚工人训练ChatGPT,看大量有害内容心理受伤——AI新时代下剥削

    原文地址: https://mbd.baidu.com/newspage/data/landingsuper?context=%7B%22nid%22%3A%22news_90623597686514 ...

  8. 【产品兼容认证】WhaleStudio 成功兼容TiDB数据库软件

    平凯星辰和白鲸开源宣布成功完成产品兼容认证 北京,2023年12月27日 - 平凯星辰(北京)科技有限公司(以下简称平凯星辰)旗下的 TiDB 产品与白鲸开源的 WhaleStudio 已成功完成产品 ...

  9. FIRD的防碰撞机制

    RFID多标签阅读时防碰撞技术 概念 RFID 读写器在正常情况下一个时间点只能对磁场中的一张RFID卡进行读或写操作,但是实际应用中经常有当多张卡片同时进入读写器的射频场,读写器怎么处理呢?读写器需 ...

  10. Java栈溢出|内存泄漏|内存溢出

    Java虚拟机栈是线程私有的,它的生命周期和线程同步 一个线程每执行到一个方法,JVM就会创建一个栈帧(用于存储基本数据类型.对象指针和返回值等),并将栈帧压入栈中. 代码示例: public cla ...