zoukankan      html  css  js  c++  java
  • 002 模板实参推断、重载与模板

    模板实参推断

    一、模板函数显示实参

    情况1:

    template <typename T1, typename T2, typename T3>
    T1 sum(T2 a, T3 b)
    {
        return a + b;
    }

    分析:调用的时候就需要指定T1的类型,如:sum<float>(1, 2); 于是sum函数的返回类型为float。

     情况2:

    template <typename T1, typename T2, typename T3> //糟糕的设计,用户必须指定所有的三个模板参数
    T3 sum(T1 a, T2 b) 
    {
        return a + b;
    }

    分析:对于sum<float>(1, 2); 现在这个调用里指定T1类型为float,但是实际传进来的是1(int类型),会进行隐式类型转换,将1转换为float. T2的类型也可以根据sum(1,2)调用的第二个实参推断出来,这里是可能会是int. 那么T3是什么类型呢?显然这里编译器无法推断T3的类型,需要在调用时指定才能推断:

    1.   sum<int, int, int>(1, 2); 这样T3就推断出来是int。 

    2. 在指定显示模板实参时指定的类型是和模板参数匹配的,顺序是一一对应的,如:

        •  使用 sum<int>(1, 2); 对上面的第一个模板进行调用,那么T1对应int,T2T3则通过推断得出。

        •  使用 sum<int>(1, 2); 对上面的第二个模板进行调用,那么T1对应的类型是int,T2可以根据实际穿进去的参数进行推断,这里2为int,那么T2类型就是int,那么编译器就无法知道T3的实际类型了。

     

     二、完美转发

    template<class T>
    void wrapper(T&& arg) 
    {
        // arg 始终是左值
        foo(std::forward<T>(arg)); // 转发为左值或右值,依赖于 T
    }  
    
    分析:
      1. 若对 wrapper() 的调用传递右值string ,则推导 T 为 std::string(非string& 或string&& ,且 std::forward 确保将右值引用传递给 foo.
      2. 若对 wrapper() 的调用传递 const 左值string ,则推导 T 为 const string& ,且 std::forward 确保将 const 左值引用传递给 foo.
      3. 若对 wrapper() 的调用传递非 const 左值string ,则推导 T 为string& ,且 std::forward 确保将非 const 左值引用传递给 foo. 

    分析:

    1. 若对 wrapper() 的调用传递右值string ,则推导 T 为 std::string(非string& 或string&& ,且 std::forward 确保将右值引用传递给 foo.

    2. 若对 wrapper() 的调用传递 const 左值string ,则推导 T 为 const string& ,且 std::forward 确保将 const 左值引用传递给 foo.

    3. 若对 wrapper() 的调用传递非 const 左值string ,则推导 T 为string& ,且 std::forward 确保将非 const 左值引用传递给 foo.

     举例

     1 #include<iostream>
     2 #include<utility>
     3 using namespace std;
     4 
     5 void g(int &&i, int &j)
     6 {
     7     cout << i << " " << j << endl;
     8 }
     9 
    10 void f(int v1, int &v2)
    11 {
    12     cout << v1 << " " << ++v2 << endl;
    13 }
    14 
    15 //flip1实现不完整:顶层const和引用都丢掉了
    16 template <typename F, typename T1, typename T2>
    17 void flip1(F f, T1 t1, T2 t2)   
    18 {
    19     f(t2, t1);
    20 }
    21 
    22 template <typename F, typename T1, typename T2>
    23 void flip2(F f, T1 &&t1, T2 &&t2)
    24 {
    25     f(t2, t1);
    26 }
    27 
    28 template <typename F, typename T1, typename T2>
    29 void flip(F f, T1 &&t1, T2 &&t2)
    30 {
    31     f(std::forward<T2>(t2), std::forward<T1>(t1));
    32 }
    33 
    34 int main()
    35 {
    36     int i = 0, j = 0, k = 0, l = 0;
    37     cout << i << " " << j << " " << k << " " << l << endl;
    38     f(42, i);         //f改变其实参i
    39     flip1(f, j, 42);  //通过flip1调用f不会改变j
    40     flip2(f, k, 42);  //正确:k被改变了
    41     g(42, i);
    42     flip(g, i, 42);   //正确:第三个参数的右值属性被保留了
    43     cout << i << j << " " << k << " " << l << endl;
    44     return 0;
    45 }

    重载与模板

  • 相关阅读:
    恰瓜恰到自己家
    在 D 天内送达包裹的能力
    火车编组
    排列小球
    为什么这段时间一直在做算法题呢
    leetcode 221 ,3,480,6,54,46,209,495
    leetcode 684.354,133,207,121,63,64,jz46,120,357
    leetcode 130,200,207,329,491,494,416,547,51
    flink单机搭建以及快速编写一个简单的java job demo运行
    leetcode 437,450,508,513,538,623,652,654,662
  • 原文地址:https://www.cnblogs.com/sunbines/p/9375847.html
Copyright © 2011-2022 走看看