auto和decltype类型推导

    xiaoxiao2023-10-31  181

    1. auto关键字推导 auto关键字的推导与木板参数推导规则一致。两个可以做简单类比,如

    template<typename T> void f(T); f(1) auto a = 1 //该处类型推导过程与f中形参类型的推导规则一致,引用类型可类比

    参考Modern C++中的描述,类型推导过程可以分为三类:

    非引用类型 非引用类型推导时,右侧赋值参数或表达式的引用或cv标记直接丢弃,然后做类型推导,如: // 返回值为右值 int dummy(){ return 0; } // ar为引用类型 int a = 0; int& ar = a; // ca为常量 const int ca = 0; // 三种类型的变量赋值,推导的类型 auto d1 = dummy() // auto为int auto d2 = ar; // auto为int auto d3 = ca; // auto为int 引用类型

    1)左值引用 对上述三种的推导结果如下:

    // 返回值为右值 int dummy(){ return 0; } // ar为引用类型 int a = 0; int& ar = a; // ca为常量 const int ca = 0; // 三种类型的变量赋值,推导的类型 auto& d1 = dummy() // 编译报错,左值引用仅能与左值关联 auto& d2 = ar; // auto为int auto& d3 = ca; // auto为 const int

    ca常量赋值给引用时,auto推导为const int。转化为模板函数推导更容易理解。template <typename T> f(T& t),调用者在调用该接口调用时,若传入为常量,显然在接口内也是不希望被修改的,所以T推导为const int更为合理,即引用类型下cv修饰符是可以保留的。对比1中的非引用类型,如果想要通过auto定义引用类型的变量,需要写为auto&,因为对引用类型推导中会丢弃引用符号,const修饰符类似。同时非引用类型和引用类型的auto类型推导,也有模板类型推导时的退化问题,这种退化主要体现在数组和函数指针的推导中。 2) 右值引用 对上述三种的推导结果如下:

    // 返回值为右值 int dummy(){ return 0; } // ar为引用类型 int a = 0; int& ar = a; // ca为常量 const int ca = 0; // 三种类型的变量赋值,推导的类型 auto&& d1 = dummy() // auto 为int类型 auto&& d2 = ar; // auto为int& auto&& d3 = ca; // auto为const int&

    最后两个的推导比较特殊,普遍引用在类型推到时遵循&折叠规则,所以在右侧表达市为左值时,auto为引用类型,并且cv修饰符保留。 auto关键字在变量声明上有一种非常有意思的写法;

    auto a = 1, &b = a;

    2. decltype关键字推导 decltype多用于对表达的的类型推导,多用于模板定义中不知道表达式具体类型时。典型用例如下:

    template<typename T> auto add(T a, T b)->decltype(a+b) //返回值类型未知,故显示说明返回值类型 { return a+b; }

    对上述几种类型的推导结果如下

    // 返回值为右值 int dummy(){ return 0; } // ar为引用类型 int a = 0; int& ar = a; // ca为常量 const int ca = 0; // decltype(dummy()) 为int&& // decltype(ar) 为int& // decltype(ca) 为const int // decl对表达式的推导结果与运算符的常规定义相同,如[]返回为引用类型,所以: // int a[10] = {} 中decltype(a[0])为int&,因为a[0]是可赋值的引用类型。

    通过上述推导结果可以看到decltype可以获取到表达式的真实类型,不会做decay处理。

    2. decltype(auto)关键字推导 decltype(auto)是C++14中引入的类型推导方式,借助它可以省去类型模板函数中对返回值的显式说明。

    int a = 1, b = 2; decltype(auto) = a + b; //其推导过程等价为decltype(a+b) c = a + b
    最新回复(0)