【C++】虽然有用,但也不常用的decltype

从C++11开始,语法里多了一个类型运算符decltype,它可以返回表达式的类型。在C++里有个typeid运算符,也能返回类型,但是decltype和typeid使用上并不太一样,typeid事实上是返回了type_info类型的一个说明,例如
【C++】虽然有用,但也不常用的decltype_第1张图片

以下所有代码均在VS2015中测试,其他编译器不知道对不对

struct A { int x; };
int main(int arg) {
	const type_info &s = typeid(A);
	cout << s.name() << endl;
}

以上代码输出

struct A

但是decltype是直接返回了测试表达式的类型,例如

int main(int arg) {
	decltype(6) j = 2;
	cout << typeid(j).name()<< endl;
	cout << j << endl;
}

以上代码输出

int
2

decltype的基本使用

decltype这个东西是英文declare type缩写,就是声明一个类型的意思。其实,decltype有点像宏定义,但又不太一样,它和sizeof的使用方式一样,虽然看上去像是函数调用的方式,但都是属于解释时执行,也就是说在解释时,这个东西就已经有结果了。

关于decltype可以简单理解为,编译器会把decltype以及括号内的东西,在编译期间一起替换为一个类型,这个类型是括号内的表达式指定的,如下面的代码

int x = 0;
decltype(x) j = 1;

可以理解为在程序实际编译时,编译器会把decltype(x)直接替换成int,最终要编译的代码如下

int x = 0;
int j = 1;

关于decltype的使用,decltype括号内可以放表达式,值类型,但是不能放类型,例如

decltype(1) a = 1; //可以
decltype(a+1) d = 2; //可以
decltype(int) c=2  //不行
decltype(a->x) c = 1; //可以
A * f =new A;
decltype(a) d = f;//可以
decltype(A) e = f;//不行

int abc();
decltype(abc()) c = 1; //可以,abc 返回类型int

可以看出,只要是可以确定类型的,decltype后面的括号内都能放,返回的类型就是括号内表达式的类型

不过,有一种返回类型可能和你预期不太一样,对比下列两组代码

int ddd = 1;
decltype(ddd) c = 1;
int ddd = 1;
decltype((ddd)) c = 1;

第二组代码decltype((ddd)),只比第一组代码给ddd多了一个括号,但第二组代码就是错误的。这就是涉及一个左右值的问题了

ddd 在第一组代码里 表示了int 类型,但在第二组内加了括号,他就变为了一个左值,就会返回一个引用,所以

decltype((ddd)) c = 1;

并非返回int,而是返回int的引用,int&

但是,也不能简单理解为就是加了括号就会变为左值。例如

	int abc();
	decltype((abc())) j = 0;

上面这个代码就是正确,因为abc是个函数,无论套多少层括号,最终就是返回int

同样,有些没有括号,也会返回是类型引用

	int ddd = 1;
	int fff;
	int ccc;
	decltype(ddd == 1 ? fff : ccc) c  =1 ;
	decltype((ddd == 1 ? fff : ccc)) c = 1;

以上也是错误的,因为C 是 int&

表达式

ddd == 1 ? fff : ccc

确实可以作为左值

在模板中使用

事实上,通过上面的代码可以看出来,如果就按上面的用法的话,好像这个东西也没有太大实际的意义,因为不管是函数,还是变量,你一定可以知道它的类型。

但是如果在模板中,就有用了,如下代码

template<typename T, typename D> auto abc(T a, D c) -> decltype(a > c ? a : c);

int main(int arg) {
	cout << typeid(abc(1, 2)).name()<<endl;
	cout << typeid(abc(1, 1.15)).name()<< endl;
	return 1;
}

如果只有模板函数定义,返回是auto,还没有定义具体实现的时候,编译器没法推断返回类型.

但是加了decltype(a > c ? a : c),编译器就能推断类型了,上述代码输出

int
double

decltype和typeid

在上面就说过,decltype更像sizeof 的使用方式,它在程序的解释阶段就已经出现了结果,而typeid则不是,typeid是在运行时出的结果,也就是说,它实际上是一个函数调用,比如要调用typeid的name函数,可以看到他确实是调用了一个name函数
【C++】虽然有用,但也不常用的decltype_第2张图片
而decltype运行,可以看到,实际运行时就已经知道了x的类型
在这里插入图片描述所以,他们功能上不太一样,decltype最终返回了一个真正的可以让编译器解释的类型,而typeid返回的是这个类型的说明。

你可能感兴趣的:(C++,c++,c语言,算法)