4.1 回顾typeof和typeid
在C++11之前的显示
int a = 0; typeof(a) b = 5;//typeof并非C++标准 //以及 int x1 = 0; double x2 = 5.5; std::cout << typeid(x1).name() << std::endl; std::cout << typeid(x1 + x2).name() << std::endl; std::cout << typeid(int).name() << std::endl; //typeid的返回值是一个左值,且其生命周期一直被扩展到程序生命周期结束。
返回的是一个
std::type_info
对象的引用,这就是所说的“返回值是一个左值”。由于返回的是引用,其生命周期与程序相同,因此其所引用的std::type_info
对象的生命周期会持续到程序结束。type_info& operator=(const type_info&) = delete;
typeid返回的std::type_info删除了复制构造函数,若想保存std::type_info,只能获取其引用或者指针
auto t1 = typeid(int); // 编译失败,没有复制构造函数无法编译 auto &t2 = typeid(int); // 编译成功,t2推导为const std::type_info& auto t3 = &typeid(int); // 编译成功,t3推导为const std::type_info*
typeid的返回值总是忽略类型的 cv 限定符,也就是typeid(const T)== typeid(T))。
虽然typeid可以获取类型信息并帮助我们判断类型之间的关系,但遗憾的是,它并不能像typeof那样在编译期就确定对象类型
4.2 使用decltype说明符
使用decltype说明符可以获取对象或者表达式的类型,其语法与typeof类似:
int x1 = 0; decltype(x1) x2 = 0; std::cout << typeid(x2).name() << std::endl; // x2的类型为int double x3 = 0; decltype(x1 + x3) x4 = x1 + x3; std::cout << typeid(x4).name() << std::endl; // x1+x3的类型为double decltype({ 1, 2 }) x5; // 编译失败,{1, 2}不是表达式
template <class A,class B, class C> //最原始的泛化函数 这个就是每次调用需要加入函数返回值类型 A sum(B b, C c) { return b + c; } sum<double>(10,15.3); template <class B, class C> auto sum(B b, C c)->decltype(b + c)//这个是c++11的写法 { return b + c; } template <class B, class C>//c++十四之后就支持auto推导 auto sum(B b, C c) { return b + c; } //现在可以这么写 decltype(auto) sum(B b, C c) 基本上无敌 //书上说auto不能用引用 但是加个 auto& 不就可以了
4.3 推导规则
个人总结就是 它括号里是什么类型就原封不动 函数是返回值类型
有几个特别的点
int x; decltype(x);//这个得到的就是int decltype((x));//这个得到int& static_assert(std::is_same_v<decltype((x)), int&>, "Type should be int&"); static_assert(std::is_same_v<decltype(x), int&>, "Type should be int&");//这个会报错 //说明(x)就是int&类型 int a[10]; decltype(a[3])//int& static_assert(std::is_same_v<decltype(a[3]), int&>, "Type should be int&");
a[3]是int&类型
4.4 cv限定符的推导
struct A { double x; }; const A* a = new A(); decltype(a->x); // decltype(a->x)推导类型为double, const属性被忽略 decltype((a->x));//加括号就会推导为 cont double &
4.5 decltype(auto)
参考4.2
4.6 decltype(auto)作为非类型模板形参占位符
#include <iostream> template<decltype(auto) N> void f() { std::cout << N << std::endl; }static const int x = 11; static int y = 7; int main() { f<x>(); // N为const int类型 f<(x)>(); // N为const int&类型 f<y>(); // 编译错误 f<(y)>(); // N为int&类型 }
这是在C++17中推出的