美文网首页
Item 3 Understand decltype

Item 3 Understand decltype

作者: Peiyiyi | 来源:发表于2018-11-02 09:37 被阅读0次

引子

decltype可以用来获取表达式类型,且通常就是我们想要的类型。

正文

首先,从最基本的情况开始,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, y;           //decltype(Point::x) 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])
{
  ...
  return c[i];
}

C++11允许对独立声明的lambda表达式返回类型进行推导,C++14扩展到支持推导所有lambda表达式和函数类型,包含多次声明的情况。

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

此处auto的使用会发生类型推导。编译器会根据函数实现推导返回值类型。

此处的auto与推导类型无关,返回值类型完全依赖于c和i。
根据Item 2的介绍,我们了解到auto作为函数返回值类型时,会自动推导返回值类型;而对于大多数容器,operator[]返回T&类型的对象。但根据Item 1我们又知道,模板类型推导过程中,引用特性会被忽略,因此:

std::deque<int> d;
...
authAndAccess(d, 5) = 10;

上述代码中,d[5]返回int&,但是auto类型推导忽略了引用,因此返回值类型是int,再用10对int赋值就无法编译了。
此时可以请decltype出马,推导返回值的准确类型啦!

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

此时,返回值类型为T&。除了函数返回值类型,decltype(auto)也可以用于初始化表达式变量类型的声明:

Widget w;
const Widget& cw = w;
auto myWidget1 = cw;  // myWidget1's type is Widget
decltype(auto) myWidget2 = cw; // myWidget1's type is const Widget&

接下来,我们继续修改函数,使它不仅可以接受左值参数,还可以接受右值参数。形式如下:

template<typename Container, typename Index>
decltype(auto) authAndAccess(Container&& c, Index i);

在使用通用引用时,要同时使用std::forward,传递参数的特性。
最终,C++11和C++14的写法如下:

template<typename Container, typename Index>
auto
authAndAccess(Container&& c, Index i)
-> decltype(std::forward<Container>(c)[i])
{
  ...
  return std::forward<Container>(c)[i];
}

template<typename Container, typename Index>
decltype(auto)
authAndAccess(Container&& c, Index i)
{
  ...
  return std::forward<Container>(c)[i];
}

将decltype应用于变量名,会产生该变量名的声明类型。变量名是左值,但它不影响decltype的行为。但是对左值表达式,情况就复杂了,使用decltype会产生左值引用。

int x = 0;
decltype(x); //type is int
decltype((x)); //type is int&

总结

  • decltype总是能获取到变量或表达式的真实类型
  • 对于类型为T的左值表达式,decltype总会返回类型T&
  • C++14支持decltype(auto)

相关文章

  • Item 3 Understand decltype

    引子 decltype可以用来获取表达式类型,且通常就是我们想要的类型。 正文 首先,从最基本的情况开始,decl...

  • [Note] Effective OC - Item 29~31

    Chapter 5. Memory Management Item 29: Understand Referenc...

  • Item 2 Understand auto type dedu

    引子 模板类型推导与auto类型推导是具有映射关系的。auto扮演T的角色,而类型限定符扮演ParamType的角...

  • Item 1Understand template type d

    引子 模板类型推导是Modern C++特性auto的基础,但模板类型推导和auto类型推导有一些区别,具体看正文...

  • decltype

    decltype是用于进行类型推导的。typeid用于运行时动态获取类型信息。返回相应变量对应的type_info...

  • decltype()

    摘要 本文是关于 decltype() 的学习笔记。各种版权都属于原作者。如果存在侵权行为,请通知本人删除。 de...

  • 无标题文章

    H1 H2 H3 H4 H5 H6 item1 item2 item3 item1 item2 item3 Pwc...

  • Python-列表

    列表 a=["item1","item2","item3","item4","item5"] 列表的操作(增、删、...

  • shift to markdown

    title title title 无序列表 item1 item2 item3 有序列表 item1 item2...

  • 2018-01-02

    # markdown 技术分享 ## h2 - item1 - item2 - item3

网友评论

      本文标题:Item 3 Understand decltype

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