目录
一、概述
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函数,当然不会真正的调用函数,只是推导而已。