美文网首页
Effective Modern C++ 学习笔记2——decl

Effective Modern C++ 学习笔记2——decl

作者: 拔丝圣代 | 来源:发表于2023-03-24 23:43 被阅读0次

推导规则

前面我们介绍过auto的类型推导规则。找到c++中,decltype也可以获取变量或表达式的类型,那么它的类型推导和auto一样吗,应该如何使用呢?

decltype与auto的推导规则并不同。例如:

int t;
const int& x= t;
auto y = x;    // y的类型 int
decltype(x) z; // z的类型 const int&
decltype(x + y) u; // u的类型 int

前面讲过,auto在推导过程中,会去掉变量本身的const和引用。而decltype则会完整地保留。

但需要注意的是:如果decltype不是直接应用在一个变量上,而是应用在一个表达式,且该表达式返回的是一个左值,那么decltype会得到一个左值引用。

具体是什么情况呢?

std::vector<int> vec = {1,2,3};
int x = 0;
int& GetItem(int i) {return x;}

decltype(vec[i]) a;     // int&
decltype(GetItem(1)) b; // int&
decltype(++x) c;        // int&
decltype((x)) d;        // int&

本例中的4种情况均属于左值表达式的情况。其中最后一种需要注意,仅仅是在x外面加了一个括号,从变量x变成了表达式(x),decltype推导的类型也就从int变成了int&。

应用场景

decltype一个常见的应用场景是,用返回值后置语法来声明模板函数。例如,我们想定义一个函数来代替容器的operator[]操作:

template<typename Container, typename Index>
auto Access(Container &c, Index i)
  -> decltype(c[i]) {
  return c[i];
}

在本例中,函数的返回值类型需要根据参数类型来确定,而正常的函数声明,返回值类型写在参数声明之前,所以没办法依赖参数。而使用返回值类型后置语法就可以避免这个问题。

C++14新特性

在c++14中,函数的返回值类型可以根据return语句自动推导,也就是对于上面的例子,省略掉尾部的decltype类型声明,只保留前面的auto,也可以编译通过。

但是,这样一来,函数返回值类型会按照模板的类型推导规则进行推导,也就是会去掉const和引用。这与decltype的推导规则并不相同。那么,如何能按照decltype的推导规则来定义返回值呢?其实可以将decltype与auto结合使用:

template<typename Container, typename Index>
decltype(auto) Access(Container &c, Index i) {
  return c[i];
}

decltype(auto)不仅能在函数返回值中使用,在变量声明的场景也可以使用:

int a;
const int& x = a;
auto y = x;           // y类型 int
decltype(auto) z = x; // z类型 const int&

相关文章

网友评论

      本文标题:Effective Modern C++ 学习笔记2——decl

      本文链接:https://www.haomeiwen.com/subject/gkigrdtx.html