【C/C++】【C++11】decltype详解

decltype

用于推导类型,对于一个给定的变量或者表达式,使用decltype可以得到其类型;

  • decltype的自动类型推断会发生在编译阶段和auto一样
  • decltype不会直接计算表达式的值

变量

#include <iostream>
#include <string>
#include <map>
#include <boost/type_index.hpp>
using namespace std;
class Test
{
public:
	int i;
	int j;
};
int main()
{  
	const int i = 0;
	const int& def_i = i;
	auto j1 = i;
	decltype(i) j2 = 15; //j2 = const int,如果decltype中是个变量,则变量的const属性会返回
	decltype(def_i) j3 = j2; //j3 = const int &,如果decltype中是个变量,则变量的const和&属性会返回

	decltype(Test::i) a; //a = int
	Test te;
	decltype(te) tmp; //tmp = class test
	
	int y = 9;
	auto&& z = y; //x左值 auto = int &, z = int &
	decltype(z) && h = y; //h = int &, 引用折叠

	using boost::typeindex::type_id_with_cvr;
	cout << type_id_with_cvr<decltype(h)>().pretty_name() << endl;

	return 0; 
}

非变量(表达式)

#include <iostream>
#include <string>
#include <map>
#include <boost/type_index.hpp>

using namespace std;

class Test
{
public:
	int i;
	int j;
};

int main()
{  
	decltype(8) k = 9; // k = int;

	int i = 0;
	int* pi = &i;
	int& iy = i;

	decltype(iy + 1) j; // j = int;
	decltype(pi) jk; //int *
	decltype(pi + 1) jk1; //int *
	decltype(*pi) jk2 = i; // int &
	//*pi是指针pi所指的对象,而且能够给这个对象赋值,所以*pi是个左值,*pi是个表达式,不是个变量;因为有*号
	//如果表达式结果能够作为赋值语句左边的值, 那么decltype后返回的就是个引用;
	//decltype后面是个非变量的表达式,并且表达式能够作为等号左边内容,返回的就是一个类似int &;
	

	decltype(i) k3; //k3 = int; i只是变量
	
	decltype((i)) k3 = i; 
	//如果在变量名外额外增加一层或多层括号,那么编译器会把这个变量当成一个表达式
	//又因为这个变量/表达式(i)可以作为等号左边的内容;最终i = int &;
	(i) = 6;

	using boost::typeindex::type_id_with_cvr;
	cout << type_id_with_cvr<decltype(i)>().pretty_name() << endl;

	return 0; 
}

函数


#include <iostream>
#include <string>
#include <map>
#include <boost/type_index.hpp>
#include <functional>
using namespace std;


int test()
{
	return 10;
}
const int&& func_test(void)
{
	return 0;
}

int main()
{  
	decltype(test()) tmp = 12; //tmp的类型是函数test的返回类型int
				   //这里编译器没有去调用函数,只是使用函数的返回值类型作为tmp的类型
	decltype(test) tmp_func; //如果直接是函数名,那么tmp_func代表一种可调用对象,有返回类型有参数类型; int __cdecl(void)
	function<decltype(test)> tmp_f = test; //声明了一个function(函数)类型,用来代表一个可调用对象;
	//它所代表的可调用对象是一个int(void)
	decltype(func_test()) te = 0; //te = int const &&
	using boost::typeindex::type_id_with_cvr;
	cout << type_id_with_cvr<decltype(te)>().pretty_name() << endl;

	return 0; 
}

用途

应付可变类型

一般decltype主要用途是应用与模板编程中;


#include <iostream>
#include <string>
#include <vector>
#include <boost/type_index.hpp>
#include <functional>
using namespace std;


template<typename T> 
class Test
{
public:
	//typename T::iterator iter; //迭代器
	decltype(T().begin) iter; //如果T = const std::vector<int>, 那么 begin =  std::vector<int>const_iterator iter
	//T后面加一个(),表示生成该类型的临时对象;调用了临时对象的begin()
	
	void get_begin(T& tmp)
	{
		iter = tmp.begin();
	}
};

template<typename T>
class Test<const T>
{
public:
	typename T::const_iterator iter; //const迭代器
	void get_begin(const T& tmp)
	{
		iter = tmp.begin();
	}
};
int main()
{  
	//常量容器需要使用常量迭代器遍历
	//C++98中要解决这种问题,需要使用类模板偏特化
	
	using tye = const std::vector<int>; //定义类型别名;
	tye arr = { 10, 3 }; //定义该类型变量,现在arr是个容器

	Test<tye> ct;
	ct.get_begin(arr);
	int x = 3;
	using boost::typeindex::type_id_with_cvr;
	cout << type_id_with_cvr<decltype(x)>().pretty_name() << endl;

	return 0; 
}

decltype(A().func()) x; 会生成临时对象的解释


#include <iostream>
#include <string>
#include <vector>
#include <boost/type_index.hpp>
#include <functional>
using namespace std;


template<typename T> 
class Test
{
public:
	//typename T::iterator iter; //迭代器
	decltype(T().begin) iter; //如果T = const std::vector<int>, 那么 begin =  std::vector<int>const_iterator iter
	//T后面加一个(),表示生成该类型的临时对象;调用了临时对象的begin()
	
	void get_begin(T& tmp)
	{
		iter = tmp.begin();
	}
};

template<typename T>
class Test<const T>
{
public:
	typename T::const_iterator iter; //const迭代器
	void get_begin(const T& tmp)
	{
		iter = tmp.begin();
	}
};



class A
{
public:
	A()
	{
		cout << "A()" << endl;
	}

	~A()
	{
		cout << "~A()" << endl;
	}

	int func() const
	{
		cout << "func()" << endl;
		return 0;
	}
};


int main()
{  

	//常量容器需要使用常量迭代器遍历
	//C++98中要解决这种问题,需要使用类模板偏特化
	
	using tye = const std::vector<int>; //定义类型别名;
	tye arr = { 10, 3 }; //定义该类型变量,现在arr是个容器

	Test<tye> ct;
	ct.get_begin(arr);

	//A().func(); //生成一个临时对象,调用临时对象的func函数 执行了A构造,A的func函数,A的析构函数
	//(const A()).func(); //同上

	decltype(A().func()) a; //a = int 根本没有构造过A类的对象
	 

	using boost::typeindex::type_id_with_cvr;
	cout << type_id_with_cvr<decltype(a)>().pretty_name() << endl;




	return 0; 
}

通过变量表达式抽取变量类型


#include <iostream>
#include <string>
#include <vector>
#include <boost/type_index.hpp>
#include <functional>
using namespace std;



int main()
{  
	vector<int> ac;
	ac.push_back(1);
	ac.push_back(2);
	vector<int>::size_type len = ac.size();
	cout << len << endl;

	decltype(ac)::size_type size = len; //抽取ac的类型,vector<int> 这行相当于vector<int>::size_type size = len;
	cout << size << endl;


	typedef decltype(sizeof(0)) u_t; // u_t 代表unsigned int
	//typedef decltype(sizeof(int)) u_t; // u_t 代表unsigned int
	u_t abc;
	abc - 1;


	using boost::typeindex::type_id_with_cvr;
	cout << type_id_with_cvr<decltype(abc)>().pretty_name() << endl;

	return 0; 
}



auto结合decltype构成返回类型后置语法


#include <iostream>
#include <string>
#include <vector>
#include <boost/type_index.hpp>
#include <functional>
using namespace std;


auto add(int i, int k) -> decltype(i + k)
{
	return i + k;
}

int& tf(int& i)
{
	return i;
}

double tf(double& d)
{
	return d;
}

template <typename T>
auto FuncTmp(T& tv) -> decltype(tf(tv)) //auto没有自动推导的含义,这里只是后置类型推断的一部分
{
	return tf(tv);
}


int main()
{  
	//auto func(int a, int b) -> int { ... };

	int i = 19;
	cout << FuncTmp(i) << endl; //19

	double d = 29.23;
	cout << FuncTmp(d) << endl; //29.23
	return 0; 
}

decltype(auto)用法

C++14

用于函数返回类型


#include <iostream>
#include <string>
#include <vector>
#include <boost/type_index.hpp>
#include <functional>
using namespace std;


template <typename T>
//T& Double(T& tv) //返回值是左值
//auto  Double(T & tv) //返回值变成右值
decltype(auto)  Double(T& tv) //把auto理解成要推导的类型,推导过程采用decltype
{
	tv *= 2;
	return tv;
}


int main()
{  
	int a = 100;
	Double(a) = 20;
	cout << a << endl;

	decltype(Double(a)) b = a; //b = int&

	using boost::typeindex::type_id_with_cvr;
	cout << type_id_with_cvr<decltype(b)>().pretty_name() << endl;


	return 0; 
}

用于变量声明中


#include <iostream>
#include <string>
#include <vector>
#include <boost/type_index.hpp>
#include <functional>
using namespace std;

int main()
{  
	int b = 100;


	int x = 1;
	const int& y = 1;
	auto z = y; //z = int, const和引用都没了
	decltype(auto) z2 = y; //z2 = const int &,auto丢掉的东西 const &,能够通过decltype捡回来;
	using boost::typeindex::type_id_with_cvr;
	cout << type_id_with_cvr<decltype(b)>().pretty_name() << endl;


	return 0; 
}

(x)


#include <iostream>
#include <string>
#include <vector>
#include <boost/type_index.hpp>
#include <functional>
using namespace std;

decltype(auto) tf1()
{
	int i = 1;
	return i; //返回int 
}

decltype(auto) tf2()
{
	int i = 1;
	return (i); //返回int &,如果要使用返回的i,栈中的东西,会导致不可预料的结果
}

int main()
{  
	int i = 10;
	decltype((i)) iy = i; //iy = int&


	decltype(tf1()) test1 = 3; //int

	//decltype(tf2()) test2 = i; //int & 语法没问题,但是程序会异常退出


	using boost::typeindex::type_id_with_cvr;
	cout << type_id_with_cvr<decltype(test1)>().pretty_name() << endl;

	return 0; 
}
posted @ 2020-08-06 11:01  NaughtyCoder  阅读(1052)  评论(0)    收藏  举报