深入篇:decltype深入分析

1.decltype一般用法(获取类型)

int fun();int main(void)
{
    int inta = 2;
    
    /*1.inta 为int.*/
    decltype(inta ) a;
    /*2.b为int,对于b根本没有定义,但是程序依旧正常,因为decltype只做分析,并不调用fun().*/
    decltype(fun()) b;return 0;
}
	double tempA = 3.0;
    const double ctempA = 5.0;
    const double ctempB = 6.0const double *const cptrTempA = &ctempA;
    
    /*1.dclTempA推断为const double(保留顶层const,此处与auto不同)*/
    decltype(ctempA) dclTempA = 4.1;
    /*2.dclTempA为const double,不能对其赋值,编译不过*/
    dclTempA = 5;
    /*3.dclTempB推断为const double * const*/
    decltype(cptrTempA) dclTempB = &ctempA;
    /*4.输出为4(32位计算机)和5*/
    cout<<sizeof(dclTempB)<<"    "<<*dclTempB<<endl;
    /*5.保留顶层const,不能修改指针指向的对象,编译不过*/
    dclTempB = &ctempB;
    /*6.保留底层const,不能修改指针指向的对象的值,编译不过*/
    *dclTempB = 7.0;

2.decltype与引用(主要是为了获取引用关系)

decltype是为了获取变量或者表达式的类型而存在,其主要作用是可以获取引用关联(&),甚至是为了确认左值!

  1. 当decltype(A),A为变量的时候,const int& i = 1;decltype(i)为const int&,即就是变量的类型;
  2. 当A为表达式的时候,如果该表达式的值是左值,则返回T&,例如int* p= 1;decltype(*p)为int&,同理deque vector等,deque< int > a{1,2,3}; decltype(a[])为int&, 因为表达式a[]可以当左值(deque里operator[]的返回值为T&,所以为左值引用类型,必为左值),同理数组的[]也是左值,如果class A里的operator[]不是左值,是返回int,decltype(a[])为int
  3. decltype可以形别推导,例如decltype(auto) 即保证形别与返回值或者=右边的值得类型完全一致!因为使用函数模板或者auto推导的时候,会去除引用&,decltype可以恢复

2.1 先区分左值与左值引用的关系

这里首先要区分左值引用、右值引用和左值、右值的关系

  1. int i = 1; int& a = i; 这里a是左值,其decltype(a)为int&,为左值引用,只能等于左值
  2. int&& b = 1; b为左值,但是其是右值引用,只能等于右值
  3. fun(T&),只能接收左值,不管其类型是左值引用还是右值引用
  4. fun(T&&),如果是万能引用则左值或者右值都能接收,但是如果确定T为int,则只能接收右值
  5. 左值是可以放在等号左边的,比如*p,或者vector()[],是可以被赋值的
  6. 右值只能放在等号右边,比如函数返回值为int,其只能在等号右边

2.2 decltype结合auto推导分析

先复习下函数模板和auto参数推导,auto与fun一致

  1. fun(T a) — 先去除&,const,例子:const int& x, fun(x)为(T为int),为值传递
  2. fun(T& a) — x只能为左值,且x要去除引用,例子,const int&& x,则T& a = const int,T为const int,PT为const int& ,x为const int&&,也就是说PT不一定为x,右值形参只能传右值,不去除&&
  3. fun(T&& a) — 万能引用,判断x为左值还是右值
  4. 注意函数参数与数组参数,void fun(int a),如果是第一种,则void()(int),如果是第二种void(&)(int),数组第一种为int,形参为int(&)[n]
    例子1:
vector<int> a{1,2,3};
auto testa = a[1];//a[1]为int&,auto为template<T> fun(T t) --去除const与&,为int
decltype(testa) = a[1]// a[1]为int&, 左边为int&

例子2:
这种auto在前的返回值,不代表是auto推导类型,而是占位,实际推导为decltype(c[i]),这里为T&

auto authandAcess(Container& c, Index i)->decltype(c[i])
1、T&
template<typename Container, typename Index>
auto authandAcess(Container& c, Index i)->decltype(c[i])
{
	return c[i];
}
2、返回的是个右值T,因为auto-return为函数模板推导,T~T&,结果会去除&,如果authandAcess(d,5= 10;会报错,因为前面函数返回了右值
template<typename Container, typename Index>
auto authandAcess(Container& c, Index i)
{
	return c[i];
}
3、C++14写法
template<typename Container, typename Index>
decltype(auto) authandAcess(Container& c, Index i))
{
	return c[i];
}
4、完美转发版本
template<typename Container, typename Index>
decltype(auto) authandAcess(Container&& c, Index i))
{
	return std::forward<Container>(c)[i];
}

Widegt w;
const Widget& cw = w;
auto myWidegt = cw;//这时符合auto T模式,值传递,const/&都消掉,myWidegt为Widegt
decltype(auto) myWidegt = cw 为const Widegt&

3. 关于测试decltype

代码:

template<typename _Tp>
    struct remove_reference11
    { typedef _Tp   type;
    int i;
    void fun(){cout<<"1111"<<endl;}};

  template<typename _Tp>
    struct remove_reference11<_Tp&>
    { typedef _Tp   type; int i;
    void fun(){cout<<"2222"<<endl;}};

  template<typename _Tp>
    struct remove_reference11<_Tp&&>
    { typedef _Tp   type; int i;
    void fun(){cout<<"3333"<<endl;}};


class testcc
{
public:
     int operator[](int num)
    {
        return num;
    }
    int a;
};
    testcc cc;
   remove_reference11<decltype(cc[2])> ppp; //int
   int i;
   remove_reference11<decltype(std::move(i))> // int&&
   vector<int> t{1,2,3}
   remove_reference11<decltype(t[1])>  //int&

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值