一、typeof和typeid关键字
typeof并不是一个标准的关键字,他是在GCC扩展中用的,使用GCC编译器的程序员可以使用typeof静态的获取操作数的具体类型。
int a = 0;
typeof(a) b = 5;//typeof(a) 为int
typeid是标准里的关键字,使用typeid运算符可以在运行时返回一个类型为type_info的对象,对象中记录了类型的标识符和类型名。
int x1 = 0;
double x2 = 5.5;
cout<<typeid(x1).name()<<endl;
cout<<typeid(x1+x2).name()<<endl;
cout<<typeid(int).name()<<endl;
typeid的不足之处是他只能在运行时起作用,无法在编译器做类型的甄别。所以decltype说明符出现了解决了这个问题。
二、decltype说明符
它的用法和typeof更加相似,他能够鉴别表达式或对象的类型。
int x1 = 0;
decltype(x1) x2 = 0; ///decltype(x1)推导类型为int类型
三、decltype的推导规则
decltype(e)(其中e的类型为T)的推导规则有5条
1、如果e是一个未加括号的标识符表达式 或 未加括号的类成员访问,则decltype(e)推断出的类型是e的类型T。
2、如果e是一个函数调用或仿函数调用,那么decltype(e)推断出的类型是返回值的类型。
3、如果e是一个类型为T的左值,则decltype(e)是T&
4、如果e是一个类型为T的将亡值,则decltype(e)是T&&
5、其他情况下decltype(e)类型为T
const int&& foo();
decltype(foo()); //满足规则2和规则4,推导类型为const int&&
int i;
decltype(i); //满足规则1,推导类型为int
struct A {
double x;
};
const A* a = new A();
decltype(a->x); //满足规则1,推导类型为double
decltype((a->x)); //满足规则3,推导类型为const double&
对于CV限定符的推导还有两条额外的规则
1、通常情况下,decltype(e)所推导的类型会同步e的CV限定符
2、当e是未加括号的成员变量时,父对象表达式的CV限定符会被忽略
四、decltype(auto),decltype和auto结合
意义是使用decltype的推导规则来推导auto
- 用decltype的推导表达式规则来推导auto
auto x1 = (i); //x1推导类型为int
decltype(auto) x2 =(i); //x2推导类型为int&
- 为非类型模版形参占位符
template<decltype(auto) N>
void f() {
cout<<N<<endl;
}
总结,decltype的主要用途是推导实体和表达式的类型,难点是它的推导规则,因为它的推导规则和auto是有一些区别的