decltype分析和std::declval源码剖析

目录

一、概述

二、decltype

1、简介

2、例子

3、总结

三、declval

1、简介

2、源码分析

3、例子


一、概述

       decltype是c++11以后出现的一个新的关键字,是用来萃取表达式或者变量或者函数返回值的类型的。 

      declval是c++11中的一个模板函数,原型如下:

       template<class T>
      typename std::add_rvalue_reference<T>::type declval() noexcept;

      返回任意类型 T 的右值引用类型,在 decltype 表达式中不必经过构造函数就能使用成员函数。
 

二、decltype

1、简介

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

2、例子

#include<iostream>
//class Silly { private: Silly( Silly const& ) = delete; };
class Silly {  };

auto foo() -> Silly&&;
int main()
{

	std::cout<< sizeof( foo() ); 
	
	decltype( foo()) a=Silly();
	std::cout<<std::endl;
    std::cout<< sizeof( a); 
}

       对于foo函数根本没有定义,但是程序依旧正常,因为decltype只做分析推断,并不调用foo函数。

int getSize();
​
int main(void)
{
    int tempA = 2;
    
    /*1.dclTempA为int.*/
    decltype(tempA) dclTempA;
    /*2.dclTempB为int,对于getSize根本没有定义,但是程序依旧正常,因为decltype只做分析,并不调用getSize().*/
    decltype(getSize()) dclTempB;
​
    return 0;
}
     对于getSize函数根本没有定义,但是程序依旧正常,因为decltype只做分析推断,并不调用getSize函数。
    const double ctempA = 5.0;
    decltype(ctempA) dclTempA = 4.1;
// dclTempA推断为const double(保留const)
    

    int tempA = 0, &refTempA = tempA;
    decltype(refTempA) dclTempA = tempA;

   // dclTempA为引用,绑定到tempA
    

    int tempA = 2;
    int *ptrTempA = &tempA;
    /*1.常规使用dclTempA为一个int *的指针*/
    decltype(ptrTempA) dclTempA;
    /*2.需要特别注意,表达式内容为解引用操作,dclTempB为一个引用*/
    decltype(*ptrTempA) dclTempB=tempA ;

3、总结

   decltype总结如下:

(1)decltype保留顶层const;

(2)对引用操作,decltype推断出引用;

(3)对解引用操作,decltype推断出引用;

(4)decltype不会执行,只做分析。

三、declval

1、简介

      declval的作用是返回模板参数类型的右值引用,declval常和c++11新引入的decltype配合使用。

2、源码分析

  template<typename _Tp>
    struct __declval_protector
    {
      static const bool __stop = false;
      static typename add_rvalue_reference<_Tp>::type __delegate();
    };

  template<typename _Tp>
    inline typename add_rvalue_reference<_Tp>::type
    declval() noexcept
    {
      static_assert(__declval_protector<_Tp>::__stop,
		    "declval() must not be used!");
      return __declval_protector<_Tp>::__delegate();
    }

   __delegate 函数实际上不会执行,而只是用来推导类型,于是这个函数不需要定义,只需要声明。

3、例子

// declval example
#include <utility>      // std::declval
#include <iostream>     // std::cout
 
struct A {              // abstract class
  virtual int value() = 0;
};
 
class B : public A {    // class with specific constructor
  int val_;
public:
  B(int i,int j):val_(i*j){}
  int value() {return val_;}
};
 
int main() {
  decltype(std::declval<A>().value()) a;  // int a
  decltype(std::declval<B>().value()) b;  // int b
  decltype(B(0,0).value()) c;   // same as above (known constructor) int c
  a = b = B(10,2).value();
  std::cout << a << '\n';
  return 0;
}

      std::declval<A>()返回A的右值引用,然后调用value函数,当然不会真正的调用函数,只是推导而已。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kupeThinkPoem

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值