美文网首页
[C++11阅读][3-3-3]decltype类型推导(中)

[C++11阅读][3-3-3]decltype类型推导(中)

作者: 凌霄阁2010 | 来源:发表于2020-07-08 00:09 被阅读0次

引子

decltype类型推导还挺复杂,有时候会出一些奇怪的错误,比如下面的程序编译不过,因为括号里的i推导成引用了。

int main() {
    int i;
    decltype(i) a;
    decltype((i)) b;
}
// cpp.cpp:5:19: error: ‘b’ declared as reference but not initialized

四规则

当程序员用decltype(e)获得类型,

  1. 如果e是一个没有带括号的标记符表达式(id-expression)或者类表达式,那么decltype(e)就是e所命名的实体的类型。此外,如果e是一个被重载的函数,则会导致编译时错误。
  2. 否则,假设e的类型是T,如果e是一个将亡值(xvalue),那么decltype(e)为T&&。
  3. 否则,假设e的类型是T,如果e是一个左值,则decltype(e)为T&。
  4. 否则,假设e的类型是T,则decltype(e)为T。
    标记符表达式就是常规理解的表达式,比如int arr[4];,arr是标记符表达式,但arr[3]就不是,已经对arr进行了操作。
    引子里的例子,a属于规则1,b属于规则3,(i)带了括号,又实实在在有地址、属于左值,因此落到了规则3。

四规则示例

int main() {
    int i = 4;
    int arr[5] = {0};
    int *ptr = arr;
    struct S { double d; } s;
    void Overloaded(int);
    void Overloaded(char);
    int && RvalRef();
    const bool Func(int);
    // 规则1
    decltype(arr) var1;  // int[5]
    decltype(ptr) var2;  // int*
    decltype(s.d) var4;  // double
    decltype(Overloaded) var5;  // error: decltype cannot resolve address of overloaded function
    // 规则2
    decltype(RvalRef()) var6 = 1;  // xrvalue, int&&
    // 规则3
    decltype(true? i : i) var7 = i;  // lvalue int&
    decltype((i)) var8 = i;  // int&
    decltype(++i) var9 = i;  // int&
    decltype(arr[3]) var10 = i;  // int&
    decltype(*ptr) var11 = i;  // int&
    decltype("lval") var12 = "lval";  // const char(&)[9]
    // 规则4
    decltype(1) var13;  // int
    decltype(i++) var14;  // int
    decltype((Func(1))) var15;  // const bool
}

上面的程序覆盖了四种规则。
关于var5,把void Overloaded(char);那行删掉就能编译通过了,没有重载的函数是可以放在decltype里的。
另外值得注意的是i++和++i那句,i++得到的是int,++i得到的是int&。这是因为++i返回的是操作后的结果,类似(i),不再是标记符表达式,有地址跟i一样,落在了规则3;i++不是i,不是规则1,但也没有地址,落在了规则4。
打印结果。

#include <type_traits>
#include <iostream>
using namespace std;
int i = 4;
int arr[5] = {};
int *ptr = arr;
int && RvalRef();
int main(){
    cout << is_rvalue_reference<decltype(RvalRef())>::value << endl; // 1
    cout << is_lvalue_reference<decltype(true? i : i)>::value << endl; // 1
    cout << is_lvalue_reference<decltype((i))>::value << endl; // 1
    cout << is_lvalue_reference<decltype(++i)>::value << endl; // 1
    cout << is_lvalue_reference<decltype(arr[3])>::value << endl; // 1
    cout << is_lvalue_reference<decltype(*ptr)>::value << endl; // 1
    cout << is_lvalue_reference<decltype("lval")>::value << endl; // 1
    cout << is_lvalue_reference<decltype(i++)>::value << endl; // 0,不是左值引用也不是右值引用,就是左值
    cout << is_rvalue_reference<decltype(i++)>::value << endl; // 0,改成is_integral就能出来1了
}

相关文章

  • [C++11阅读][3-3-3]decltype类型推导(中)

    引子 decltype类型推导还挺复杂,有时候会出一些奇怪的错误,比如下面的程序编译不过,因为括号里的i推导成引用...

  • C++11的类型推导详解

    auto & decltype 关于C++11新特性,最先提到的肯定是类型推导,C++11引入了auto和decl...

  • C++11中auto和decltype

    C++11中auto和decltype auto和decltype都是C++11中引进来用于自动推断类型的关键字,...

  • C++11类型推导

    C++11 重新定义了auto 和 decltype 这两个关键字实现了类型推导,让编译器来操心变量的类型。 au...

  • 模板函数返回类型的演进

    提纲 c++03: trick 方法 c++11: auto->decltype 组合 c++14: 自动推导模板...

  • C++11 类型推导,auto和decltype

    本文根据众多互联网博客内容整理后形成,引用内容的版权归原始作者所有,仅限于学习研究使用,不得用于任何商业用途。 a...

  • decltype关键字

    C++11新标准学习:decltype关键字 1. decltype的意义 有时我们希望从表达式的类型推断出要定义...

  • [C++11阅读][3-3-2]decltype类型推导(上)

    表达式推导 如下面的例子,decltype的类型推导并不是像auto一样从变量声明的初始化获得变量类型,而是以一个...

  • [C++11阅读][3-3-4]decltype类型推导(下)

    cv限制符 decltype可以带走cv限制符,这一点跟auto不同,auto带不走。但cv限制符不会扩散到成员变...

  • nullptr

    decltype 用于类型推导,而 std::is_same 用于比较两个类型是否相同. 将输出: 结论 NULL...

网友评论

      本文标题:[C++11阅读][3-3-3]decltype类型推导(中)

      本文链接:https://www.haomeiwen.com/subject/uuzaqktx.html