• 第3课 类型推导(3)_追踪返回类型


    1. 追踪返回类型的引入

    (1)经典问题:泛型编程中的返回值类型(被迫引入了返回值类型R作为模板参数)

    template<typename R, typename T, typename U>
    R add(T t, U u)
    {
        return t + u;
    }
    
    int a = 1; float b = 2.0
    auto c = add<decltype(a+b)>(a,b); //不能自动推导函数的返回值。为了获得返回值的类型,该函数的使用者需要知道add函数的内部实现(如:a+b)

    (2)decltype的尴尬

    template<typename R, typename T, typename U>
    decltype(t + u) add(T t, U u)  //编译出错,因为编译器是从左向右读入符号,而返回值是前置语法,定义返回值时t、u参数尚未定义。
    {
        return t + u;
    }

    (3)不完美的解决方案——写法过于晦涩难懂

    template<typename R, typename T, typename U>
    decltype((*(T*)0) + (*(U*)0)) add(T t, U u)  //技巧:利用0地址进行类型转换
    {
        return t + u;
    }

    2. 返回类型后置(trailing-return-type, 又称为追踪返回类型

    (1)利用追踪返回类型进行的等价函数声明

      ①函数指针的等价:如,auto (*fp)() -> int 与int (*fp)()的等价;

      ②函数引用的等价:如,auto  (&fr)() -> int 与 int (&fr)()的等价

    (2)利用auto + decltype的结合进行追踪返回类型

    template<typename R, typename T, typename U>
    auto add(T t, U u) -> decltype(t + u) //返回类型后置
    {
        return t + u;
    }

    【实例分析】使用追踪返回类型的函数

    //3.1.cpp

    #include <iostream>
    using namespace std;
    
    //1. 追踪返回值类型
    template<typename T1, typename T2>
    auto Add(const T1& t1, const T2& t2) ->decltype(t1 + t2)
    {
        return t1 + t2;
    }
    
    template<typename T1, typename T2>
    auto Mul(const T1& t1, const T2& t2) ->decltype(t1 * t2)
    {
        return t1 * t2;
    }
    
    //2. 晦涩的面试题
    int (*(*pf())())(){
        return nullptr;
    }
    
    //pf1是个函数,无参,返回值类型是auto(*)() ->int (*)()
    //而auto(*)() ->int (*)表示是一个函数指针(具体类型可按同样的
    //方法从右向左解析出来)
    auto pf1() -> auto(*)() -> int (*)(){
        return nullptr;
    }
    
    //函数转发
    double foo(int a){
        return (double)a + 0.1;
    }
    
    int foo(double b){
        return (int)b;
    }
    
    template<typename T>
    auto Forward(T t) -> decltype(foo(t)){ //根据实际调用的foo(t)追踪其返回值类型
        return foo(t);
    }
    
    int main()
    {
        ////////////////////////////////////////////////////
        //1. 追踪返回值类型(该例比较特殊,没有指明任何的具体类型)
        //   更像是动态类型语言的代码,而不像严格静态类型的C++代码
        auto a = 3;
        auto b = 4L;
        auto pi = 3.14;
        
        auto c = Mul(Add(a, b), pi);
        cout << c << endl; //21.98
        
        ////////////////////////////////////////////////////
        //2. 简化函数定义
        cout << is_same<decltype(pf), decltype(pf1)>::value<< endl; //1,pf和pf1函数的类型完全相同!
        
        //3. 转发函数
        cout << foo(2) << endl;
        cout << foo(0.5) << endl;
        
        cout << Forward(2) << endl;
        cout << Forward(0.5) << endl;
        
        return 0;
    }
  • 相关阅读:
    C#构造方法重载
    coffeeScript 语法总结
    JavaScript常用代码段
    CSS选择器,CSS3选择器
    CSS实用的代码段
    Gdb 调试
    Keras同时有多个输出时损失函数计算方法和反向传播过程
    PyTorch 速查
    Keras自定义Layer使用说明
    TensorFlow Variable 和 Tensor 的区别
  • 原文地址:https://www.cnblogs.com/5iedu/p/6937982.html
Copyright © 2020-2023  润新知