首页 > 编程语言 >C++填坑系列——类型推导 decltype

C++填坑系列——类型推导 decltype

时间:2024-03-02 12:44:50浏览次数:25  
标签:decltype 推导 int auto C++ 填坑 类型 表达式

decltype

decltype主要是为了解决类型推导的问题,特别是在模板编程和泛型编程中应用较广泛。
decltype关键字用于以表达式为参数,推导表达式返回的类型,该类型会保留所有信息。

c++11提出的新特性,decltype关键字。

auto一样都是用来做编译时类型推导的,但是也有一些区别:

  • auto: 从变量声明的表达式中推导变量类型,如:auto a = b + c;
  • decltype: 以表达式为参数,推导表达式返回的类型,如:decltype(a+b) c;

用法:

1. decltype+变量

会推导出该变量类型的所有信息(包括constreference),数组和函数也不会退化;

int main() {
  int arr[2] = {0, 1};
  int* p = arr;
  int a = 10;
  int& b = a;
  const int c = 20;
  const int& d = a;
  decltype(a) e1;         // int
  decltype(b) e2 = a;     // int& 保留引用的信息
  decltype(c) e3 = 10;    // const int 保留const的信息
  decltype(d) e4 = a;     // const int& 保留const和引用的信息
  decltype(arr) e5;       // int[2] 推导出类型还是数组
  decltype(p) e6;         // int *  推导出类型还是指针
}

2. decltype+表达式

会返回表达式结果对应的类型;表达式的结果分为左值/右值,左值->得到该类型的左值引用;右值->得到该类型;

注意下面代码Sample的第2和第3个结果,推导出的类型不一样,这是因为:
decltype单独作用于对象,没有使用该对象的表达式属性,而是该变量;要想使用表达式,可以加括号。
decltype(s)这里推导对象s的类型就是Sampledecltype((s))这里推导表达式结果的类型,左值得到左值引用类型。

class Sample {};
int func1() { return 10; }
Sample& func2(Sample& s) { return s; }

int main() {
  int a = 10;
  int& b = a;
  decltype(a + b) e11;    // int, 表达式a+b的结果是个右值
  decltype(func1()) e12;   // int, 函数func()返回的结果是个右值

  Sample s;
  decltype(std::move(s)) e13 = std::move(s);  // 1. Sample&&
  decltype(s) e14;                            // 2. Sample
  decltype((s)) e15 = e14;                    // 3. Sample&
  decltype(func2(s)) e16 = e14;               // 4. Sample&
  return 0;
}

3. 如何执行?

decltype并不会实际计算表达式的值,编译器只会分析表达式结果并得到类型;这个注意和auto的区分。

4. 使用场景:

  1. 不需要计算;

有些场景需要从表达式只是推导出类型,而不需要确切的计算,以及不需要使用表达式的值初始化另一个变量;

auto a = b + c;虽然可以推导类型,但是会使用表达式初始化另一个变量;

decltype(b + c) a;这里只会用a+b的结果推导类型,并不会真的执行运算。

  1. (trailing return type)auto配合;

c++11引入的尾置返回类型(trailing return type)decltype可以有更好的配合。

c++11之前,函数模板的返回类型不能依赖于模板参数推导。

c++11之后,尾置返回类型允许使用auto关键字,然后在函数参数声明之后推导返回类型。
下面的代码一,使用auto自动推导函数返回类型编译器会报错:auto函数需要尾随的返回类型(c++11会报错,但在c++14解决了该问题)",所以在代码二中,可以结合decltype来进行自动推导,decltype(lhs + rhs)用于推导两个参数相加的结果类型。

// 代码一:
// c++11中会报错:“auto”函数需要尾随的返回类型
// c++14中不会报错,可以直接使用auto来推导
template <typename T, typename U>
auto add(const T& lhs, const U& rhs) {
  return lhs + rhs;
}
// 代码二:c++11中添加-> decltype(lhs + rhs)可编译通过了就
template <typename T, typename U>
auto add(const T& lhs, const U& rhs) -> decltype(lhs + rhs) {
  return lhs + rhs;
}

(trailing return type)
在模板编程和泛型编程中,解决传统函数返回类型声明中的一些限制,使得函数的返回类型可以很好地依赖于其参数类型;
通过decltype尾置,来自动推导依赖参数的类型

  1. 处理复杂的返回类型时;

在模板编程中,有时候需要处理非常复杂的类型,或者类型依赖于模板参数。而decltype可以帮我们很准确地推导出类型。

下面的代码中,利用decltype推导Container的迭代器类型,当然这个位置和auto的使用功能差不多了就。

template <typename Container>
void foo(const Container& c) {
  decltype(c.begin()) it1 = c.begin();
  auto it2 = c.begin();
}

标签:decltype,推导,int,auto,C++,填坑,类型,表达式
From: https://www.cnblogs.com/pplearn/p/18048496

相关文章

  • C++填坑系列——左值和右值
    c++的表达式首先介绍下c++的表达式是什么?看下cppreference是怎么说的。Anexpressionisasequenceofoperatorsandtheiroperands,thatspecifiesacomputation.也就是说,在C++中,表达式(Expression)是由操作数(Operands)和运算符(Operators)组成的序列。左值和右值就是c++中......
  • C++填坑系列——lambda表达式
    lambda表达式总结:lambda表达式原理:被编译器转换为类+初始化对象的代码;格式:[captureslist](paramslist)specifiersexception->retType{funtionbody}按值捕获和按引用捕获的优缺点以及解决方法;一.lambda原理lambda函数会被编译器转换为类,并定义实现一个operato......
  • C++ 类访问修饰符
    私有(private)成员成员和类的默认访问修饰符是private,如果没有使用任何访问修饰符,类的成员将被假定为私有成员。私有成员变量或函数在类的外部是不可访问的,甚至是不可查看的。只有类和友元函数可以访问私有成员。实际操作中,我们一般会在私有区域定义数据,在公有区域定义相关的函数......
  • C++类开发的第六篇(虚拟继承实现原理和cl命令的使用的bug修复)
    Class_memory接上一篇末尾虚拟继承的简单介绍之后,这篇来详细讲一下这个内存大小是怎么分配的。使用clcl是MicrosoftVisualStudio中的C/C++编译器命令。通过在命令行中键入cl命令,可以调用VisualStudio的编译器进行编译操作。cl命令提供了各种选项和参数,用于指定源......
  • C++ 把引用作为返回值
    通过使用引用来替代指针,会使C++程序更容易阅读和维护。C++函数可以返回一个引用,方式与返回一个指针类似。当函数返回一个引用时,则返回一个指向返回值的隐式指针。这样,函数就可以放在赋值语句的左边。例如,请看下面这个简单的程序:1#include<iostream>23usingnamesp......
  • C++ 类的内存布局
    基类类内成员的内存分布常见类内成员大致分为:类内变量、类内函数、静态变量、虚函数等,内存分布遵循:所有成员会按照声明的顺序布局类内成员会进行大对齐类内函数不占用类的内存,存储在代码区静态变量不占用类的内存,存储在全局/静态区所有虚函数共用一个虚函数表指针,虚函数表......
  • C++ 把引用作为参数
    1#include<iostream>2usingnamespacestd;34//函数声明5voidswap(int&x,int&y);67intmain()8{9//局部变量声明10inta=100;11intb=200;1213cout<<"交换前,a的值:"<<a<<en......
  • C++ 从函数返回指针
    C++允许从函数返回指针,必须声明一个返回指针的函数:int*myFunction()C++不支持在函数外返回局部变量的地址,除非定义局部变量为static变量。1#include<iostream>2#include<ctime>3#include<cstdlib>4 5usingnamespacestd;6 7//要生成和返回随......
  • C++ 指针 vs 数组
    指针和数组并不是完全互换的1#include<iostream>23usingnamespacestd;4constintMAX=3;56intmain()7{8intvar[MAX]={10,100,200};910for(inti=0;i<MAX;i++)11{12*var=i;//这是正确的语法13......
  • C++类开发第五篇(继承和派生的初体验)
    inheritance在C++中,继承是一种面向对象编程的特性,允许一个类(称为子类或派生类)从另一个类(称为基类或父类)那里继承属性和行为。通过继承,子类可以获得父类的数据成员和成员函数,从而可以重用父类的代码并扩展其功能。这样可以提高代码的复用性和可维护性,同时也符合面向对象编程的封......