• C++11 追踪返回类型


    【1】追踪返回类型的引入

    为什么要引入追踪返回类型?

    在C++98中,如果一个函数模板的返回类型依赖于实际入口参数类型,那么该返回类型在模板实例化之前可能都无法确定。

    还记得Sum模板函数吗?请看如下演化过程:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 // 演化1 (限制了Sum的使用范围)
     5 template <typename T1, typename T2>
     6 double Sum(T1& t1, T2& t2)
     7 {
     8     auto s = t1 + t2;
     9     return s;
    10 }
    11 
    12 // 演化2 (改变了Sum的使用方式,不可以完全接受)
    13 template <typename T1, typename T2>
    14 void Sum(T1& t1, T2& t2, decltype(t1 + t2)& s)
    15 {
    16     s = t1 + t2;
    17 }
    18 
    19 // 演化3 (编译失败,思考为什么?)
    20 #if 0
    21 template <typename T1, typename T2>
    22 decltype(t1 + t2) Sum(T1& t1, T2& t2)
    23 {
    24     return (t1 + t2);
    25 }
    26 #endif
    27 
    28 
    29 // 演化4 (即追踪返回类型)
    30 template <typename T1, typename T2>
    31  auto Sum(T1& t1, T2& t2) -> decltype(t1 + t2)
    32 {
    33     return (t1 + t2);
    34 }
    35 
    36  int main()
    37  {}

    如上演化4 的写法:

    将函数的返回值移至参数声明之后,复合符号->decltype(t1 + t2)被称为追踪返回类型,而原本函数返回值的位置由auto关键字占据。

    如此这样,就可以由编译器来推导Sum函数模板的返回类型。

    auto占位符和->return_type也就是构成追踪返回类型函数的两个基本元素。

    【2】使用追踪返回类型的函数

    (1)追踪返回类型的函数与普通函数的区别:

    最大区别在于返回类型后置。如下两种写法的示例:

    1  // 普通函数声明
    2  int func(char* a, int b);
    3 
    4  // 追踪返回类型的函数声明
    5  auto func(char* a, int b) -> int;

    除过上节中提到使模板中的一些类型推导成为一种可能而外,其他使用:

    (2)追踪返回类型声明的函数也会带给大家一些喜出望外的效果:如下示例:

     1 class OuterType
     2  {
     3      struct InnerType { int i; };
     4      InnerType GetInner();
     5      InnerType it;
     6  };
     7 
     8  // 可以不写OuterType::InnerType
     9  auto OuterType::GetInner()->InnerType
    10  {
    11      return it;
    12  }

    (3)简化函数的定义。常见于函数指针中,如下示例:

     1 #include <type_traits>
     2 #include <iostream>
     3 using namespace std;
     4 
     5  // 有时候,你会发现这是面试题
     6  int (*(*pf()) ()) ()
     7  {
     8      return nullptr;
     9  }
    10 
    11  // 一个返回函数指针的函数(假设为func函数)
    12  // auto (*)()->int(*)();
    13  // 一个返回func函数的指针的函数
    14  // auto pf1()->auto (*)() -> int(*)();
    15 
    16  auto pf1() -> auto(*)() -> int (*)()
    17  {
    18      return nullptr;
    19  }
    20 
    21  int main()
    22  {
    23      cout << is_same<decltype(pf), decltype(pf1)>::value << endl;  // 1
    24  }

    (4)广泛应用在转发函数中。如下示例:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 double foo(int a)
     5 {
     6     return (double)a + 0.1;
     7 }
     8 
     9 int foo(double b)
    10 {
    11     return (int)b;
    12 }
    13 
    14 template <class T>
    15 auto Forward(T t) -> decltype(foo(t))
    16 {
    17     return foo(t);
    18 }
    19 
    20 int main()
    21 {
    22     cout << Forward(2) << endl;    // 2.1
    23     cout << Forward(0.5) << endl;  // 0
    24 }

    good good study, day day up.

    顺序 选择 循环 总结

  • 相关阅读:
    Linux w命令
    01.drf文档及外键字段反序列化
    redis的参数解释
    redis集群复制和故障转移
    codis原理及部署_01
    redis 主从哨兵02
    redis 主从哨兵01
    redis持久化
    redis python操作
    redis cluster
  • 原文地址:https://www.cnblogs.com/Braveliu/p/12245698.html
Copyright © 2020-2023  润新知