C++11 decltype 的用法

C++11 decltype 的用法文章目录decltype的意义decltype的用法1.推导规则2.举例说明3.模版案例更多细节问题C++14取消decltype其他decltype的意义参考博客:C++11新标准:decltype关键字有时我们希望从表达式的类型推断出要定义的变量类型,但是不想用该表达式的值初始化变量(如果要初始化就用auto了)。为了满足这一需求,C++11新标准引入了decl…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

decltype 的意义


参考博客:C++11新标准:decltype关键字

  • 有时我们希望从表达式的类型推断出要定义的变量类型,但是不想用该表达式的值初始化变量(如果要初始化就用auto了)。为了满足这一需求,C++11新标准引入了decltype类型说明符,它的作用是选择并返回操作数的数据类型,在此过程中,编译器分析表达式并得到它的类型,却不实际计算表达式的值。

  • 我们之前使用的typeid运算符来查询一个变量的类型,这种类型查询在运行时进行。RTTI机制为每一个类型产生一个type_info类型的数据,而typeid查询返回的变量相应type_info数据,通过name成员函数返回类型的名称。同时在C++11中typeid还提供了hash_code这个成员函数,用于返回类型的唯一哈希值。RTTI会导致运行时效率降低,且在泛型编程中,我们更需要的是编译时就要确定类型,RTTI并无法满足这样的要求。编译时类型推导的出现正是为了泛型编程,在非泛型编程中,我们的类型都是确定的,根本不需要再进行推导。

  • 而编译时类型推导,除了我们说过的auto关键字,还有本文的decltype。

  • decltype与auto关键字一样,用于进行编译时类型推导,不过它与auto还是有一些区别的。decltype的类型推导并不是像auto一样是从变量声明的初始化表达式获得变量的类型,而是总是以一个普通表达式作为参数,返回该表达式的类型,而且decltype并不会对表达式进行求值。

decltype 的用法


1. 推导规则

参考博客:C++11新标准:decltype关键字

  • 如果e是一个没有带括号的标记符表达式或者类成员访问表达式,那么的decltype(e)就是e所命名的实体的类型。此外,如果e是一个被重载的函数,则会导致编译错误
  • 否则 ,假设e的类型是T,如果e是一个将亡值,那么decltype(e)为 T&&
  • 否则,假设e的类型是T,如果e是一个左值,那么decltype(e)为 T&
  • 否则,假设e的类型是T,则 decltype(e)为 T

2. 举例说明

参考博客:C++11特性:decltype关键字

// #pragma GCC diagnostic error "-std=c++11"

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

using namespace std;

// example
int foo();
int bar();
int bar(int x);

// 泛型编程中结合 auto,用于追踪函数的返回值类型
template <typename _Tx, typename _Ty>
auto multiply(_Tx x, _Ty y)->decltype(_Tx * _Ty)
{ 
   
    return x*y;
}

int main() { 
   

    // 1-基本用法
    double a = 2;
    decltype(a) a1; cout << typeid(a1).name() << endl;

    // 2-只推断类型,不调用函数
    decltype(foo()) b; cout << typeid(b).name() << endl;

    // 3-与 const 结合
    double c = 3.0;
    decltype(c) c1; cout << typeid(c1).name() << endl;
    decltype(c) c2 = 3.2;

    const double d = 5.0;
    // decltype(d) d1; // err, 推断出师 const double,所以必须初始化赋值
    decltype(d) d2 = 6.3; cout << typeid(d2).name() << endl;
    decltype(d) d3 = 5.2; // err, 不允许赋值

    const double * const e = &c;
    // decltype(e) e2 = 1.2; // err, 不允许赋值
    decltype(e) e3 = &a;
    // *e3 = 3.5; // err, 不允许改变值

    // 4-与 reference 结合
    int f = 0, &rf = f;
    decltype(rf) rf1 = f; // 推断出为 reference, 正确
    // decltype(rf) rf2 = 0; // 必须引用变量,不能使常量
    // decltype(rf) rf3; // 必须初始化
    decltype((f)) rf4 = f; // f 为左值,(f)为左值表达式即为引用,所以引用要初始化

    const int g = 1, &rg = g;
    decltype(rg) rg1 = g; // 引用 const 变量
    decltype(rg) rg2 = 1; // 引动常量
    // decltype(rg) rg3; // err, 必须初始化

    // 5-与指针结合
    int h = 2;
    int *ptrH= &h;
    decltype(ptrH) ptrH2;
    // decltype(*ptrH) ptrH3; // err, 表达式内容为解指针操作,ptrH3 为一个引用,引用必须初始化,故编译不过

    // 6-与 using / typedef 结合
    using size_t = decltype(sizeof(0)); //sizeof(0)的返回值为 size_t 类型
    using ptrdiff_t = decltype((int*)0 - (int*)0);
    using nullptr_t = decltype(nullptr);

    vector<int> vec;
    typedef decltype(vec.begin()) vectype;
    for (vectype i = vec.begin(); i != vec.end(); i++)
    { 
   
        //...
    }

    // 6-使用匿名类型
    struct
    { 
   
        int d ;
        double b;
    }anon_s;
    decltype(anon_s) as ; // 定义了一个上面匿名的结构体

    // 7-泛型编程中结合 auto,用于追踪函数的返回值类型
    // 见第 14 行

    // 8-推导重载函数错误
    decltype(bar()) i1; // 注意这个是对的
    // decltype(bar) i2; // err, 这个是错的,因为构成了重载

    // 9-特别注意
    int j = 0;
    decltype(false ? j : 0) k; // 条件表达式返回的是左值,类型 T&

    int arr[10];
    decltype(arr) arr2; cout << sizeof(arr2) << endl; // 类型是 int [10]

    cout << "Hello world!" << endl;

    return 0;
}

3. 模版案例

参考博客:decltype 指定符

#include <iostream>

struct A { 
    double x; };
const A* a;

decltype(a->x) y;       // y 的类型是 double (声明类型)
decltype((a->x)) z = y; // z 的类型是 const double& (左值表达式)

template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) // 返回类型依赖于模板形参
{ 
   
    return t+u;
}

int main()
{ 
   
    int i = 33;
    decltype(i) j = i * 2;

    std::cout << "i = " << i << ", " << "j = " << j << '\n';

    auto f = [](int a, int b) -> int
    { 
   
        return a * b;
    };

    decltype(f) g = f; // lambda 的类型是独有且无名的
    i = f(2, 2);
    j = g(3, 3);

    std::cout << "i = " << i << ", " << "j = " << j << '\n';
}

更多细节问题


参考博客:关注C++细节——C++11新标准之decltype的使用注意

C++14 取消 decltype


参考博客:c++标准14取消decltype推算函数返回类型

其他


  1. typeid().name() 返回值
  2. C++里auto,decltype,typeid的用法
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/197286.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • HBASE的MAPREDUCE任务运行异常解决办法,无需CYGWIN,纯WINDOWS环境

    HBASE的MAPREDUCE任务运行异常解决办法,无需CYGWIN,纯WINDOWS环境

    2021年8月22日
    68
  • 全球首款AI芯片_全球AI五强

    全球首款AI芯片_全球AI五强前言你一定听说过CPU、GPU,但是TPU、VPU、NPU、XPU…等等其他字母开头的“xPU”呢?AI概念在几年前火爆全球,科技巨头们纷纷投入AI芯片的研发,小公司也致力于提出概念靠AI浪潮融资,为了快速在AI市场上立足,也为了让市场和用户能记住自家的产品,各家在芯片命名方面都下了点功夫,既要独特,又要和公司产品契合,还要朗朗上口,也要容易让人记住。前文所提到的“xPU”的命名方式就深受各大厂商的喜爱。本文就从字母A到Z来盘点一下目前各种“xPU”命名AI芯片,以及芯片行业里的各种“xPU

    2025年7月10日
    4
  • SSH服务器拒绝密码,再试一次;PermitRootLogin yes无效问题

    SSH服务器拒绝密码,再试一次;PermitRootLogin yes无效问题最近有小伙伴xshell远程登录时,出现了如下情况:网上找的答案也是千篇一律,大多数都是说将PermitRootLogin设置为yes,重启即可,然而很多并不行。在这里,说一下所有解决办法吧,总有一个适合你:如果没有安装ssh,即看不见PermitRootLogin,则使用如下语句安装:sudoapt-getinstallopenssh-server使用vim/etc/s…

    2022年6月11日
    30
  • JAVA中&&和&、||和|的区别?「建议收藏」

    JAVA中&&和&、||和|的区别?「建议收藏」问题一:JAVA中&amp;&amp;和&amp;、||和|(短路与和逻辑与、短路或和逻辑或)的区别?首先名称是不同的&&逻辑与  ||逻辑或  它们都是逻辑运算符& 按位与  | 按位或  它们都是位运算符if(a==1&&b==2) 这是说既要满足a=1也要满足b=2if(a==1||b==2) 这是说或者满足a=1或者要满足b=2而a&b或者a|b则是二进制的与…

    2022年7月7日
    20
  • 20222.5idea激活码-激活码分享

    (20222.5idea激活码)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html40…

    2022年3月13日
    51
  • 游戏php是什么文件夹,ldsgamemaster是什么文件夹

    游戏php是什么文件夹,ldsgamemaster是什么文件夹ldsgamemaster是鲁大师的游戏大师源文件;而源文件就业是用汇编语言或高级语言,写出来的代码保存为文件后的结果,目标文件是指源文件经过编译程序产生的,能被cpu直接识别的二进制文件。本教程操作环境:Windows7系统,鲁大师6.1021.3070.205版本,DellG3电脑。ldsgamemaster是鲁大师的游戏大师源文件。源文件是用汇编语言或高级语言,写出来的代码保存为文件后的…

    2022年6月12日
    52

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号