Things to Remember:
- decltype几乎总是生成变量或者表达式的类型不需要任何的修改。
- 对于类型T的lvalue表达式(除了名称),decltype总是报告出T&
- C++14支持decltype(auto),看上去像是类似于auto,能从初始化器推导出类型,但是其遵循decltype的推导规则。
const int i = 0;//decltype(i) is const int
bool f(const Widget& w);//decltype(w) is const Widget&
//decltype(f) is bool(const Widget&)
struct Point{
int x;//decltype(Point::x) is int
int y;//decltype(Point::y) is int
};
Widget w;//decltype(w) is Widget
if(f(w))//decltype(f(w)) is bool
template<typename T>
class vector{
public:
...
T& operator[](std::size_t index);
};
vector<int> v;//decltype(v) is vector<int>
if(v[0] == 0)..//decltype(v[0]) is int&
在C++11,decltype的主要用途是声明函数模板,函数的返回类型取决于其参数类型。
template<typename Container,typename Index>
auto authAndAccess(Container& c,Index i)
->decltype(c[i])
{
authenticateUser();
return c[i];
}
//Tips:使用auto和decltype推导类型这个适用于C++11,在C++14标准中已经取消
//C++14可以直接使用auto
在上述例子中,auto不是用来进行type deduction,而是C++11的新特性trailing return type(尾置返回类型)在作用。
trailing return type 跟在形参列表之后,并且用一个->符号开头。任何函数都可以使用trailing return type,但是返回类型比较复杂的函数使用它最有效。
标准改变:C++11只允许single-statement lambdas被类型推导,C++14则扩展了 所有的lambdas和所有的functions都可以被推导。当然也就包括我们上面例子中的authAndAccess,这就意味着 C++14中我们可以省略 trailing return type类型,只留下auto。实际上,这就意味着编译器可以通过function‘s implement 去推导出function’s return type。
template<typename Container,typename Index>
auto authAndAccess(Container& c,Index i)
{
authenticateUser();
return c[i];
}
}
operator[] 对于多数 containers-T 返回一个T&,但是在Item 1中得知,对于template 类型推导,一个初始化表达式的reference-ness是被忽略的。
std::deque<int> d;
authAndAccess(d,5) = 10;//return d[5]
//then assign 10 to it;but this won't compile!
d[5]返回是int&,由于auto类型推导,退步为返回int类型。此时作为一个function的返回类型,返回值是一个rvalue,不能被赋值。
template<typename Container, typename Index>
decltype(auto) authAndAccess(Container& c, Index i)
{
authenticateUser();
return c[i];
}
authAndAccess(d, 5) = 10;//Ok!
现在authAndAccess将会真正的c[i]返回的类型。
authAndAccess的改进:
上述的例子,都是passed by lvalue-reference-to-non-const,因此返回一个这个容器中元素的引用,允许修改。同时也意味着当前不能传入一个rvalue。Rvalue不能绑定到lvalue引用。(除非是 lvalue-references-to-const)