【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;
}
知识的价值不在于占有,而在于使用

浙公网安备 33010602011771号