对于给定的名字或表达式,decltype
能告诉你改名字或表达式的类型;考虑如下代码:
const int i = 0; //decltype(i)是const int
bool f(const Widget &w); // decltype(w)是const Widget &
// decltype(f)是bool f(const Widget&)
struct Point { // decltype(Point::x)是int
int x,y;
};
Widget W; // decltype(w)是Widget
if (f(w)) ... // decltype(f(w))是bool
vector<int> v; // decltype(v)是vector<int>
if (v[0] == 0) ... // decltype(v[0])是int&
C++11
中,decltype
的主要用途大概就在于声明那些返回值类型以来与形参类型的函数模板;如:
template<typename Container, typename Index>
auto authAndAccess(Container &c, Index i)
-> decltype(c[i])
{
authenticateUser();
return c[i];
}
采用这么一个声明后,operator[]
返回值是什么类型,authAndAccess
的返回值就是什么类型,和我们期望的结果一致;
而在C++14
中可以去掉返回值类型尾序语法:
template<typename Container, typename Index> // C++14
auto authAndAccess(Container &c, Index i) // 不一定正确
{
authenticateUser();
return c[i];
}
条款2说过:编译器会对auto
指定为返回类型的函数实现模板类型推导:
std::deque<int> d;
// ...
authAndAccess(d, 5) = 10;
上述代码中d[5]
返回的是int&
,但是对于authAndAccess
的返回值实施auto
类型推导将剥去引用饰词,这么一来返回值类型就成了int
,将10赋值给一个右值int
显然是错误的;
想要authAndAccess
正确运行,就要对返回值实施decltype
类型推导,在C++14
中通过decltype(auto)
饰词解决了这个问题:
template<typename Container, typename Index> // C++14能够运作,但仍亟须改进
decltype(auto)
authAndAccess(Container& c, Index i)
{
authenticateUser();
return c[i];
}
现在一般情况下c[i]
返回T&
,authAndAccess
也会返回T&
,若你也想在初始爱护表达式处应用decltype
类型推导规则,也可以照样操作:
Widget w;
const Widget& cw = w;
auto myWidget1 = cw; // auto类型推导:myWidget1的类型是Widget
decltype(auto) myWidget2 = cw; // decltype类型推导,myWidget2的类型是cosnt Widget&