zoukankan      html  css  js  c++  java
  • [编程语言]C++函数模板笔记-1

    函数模板

    函数模板的基本形状

        template <typename T>
        T fun(T val1, T val2)
        {
            return val1*val2;
        }
    
    

    开头的template表示接下来的函数是一个模板函数

    其中的typename也可以用class来替代.

    T在之后的函数里可以用来代指函数类型.你也可以把它改成其他名字,然后用到它的地方也改成对应的名字就行.

    总之,必须以template这个关键字开头,后面一个<typename T>或者<class T>, T只是一个标识符,不是固定搭配,可以任意写.

    再之后就是写你想要的函数.

    要注意,函数里用到的操作符对于传进去的参数的类型必须要合法

    例如, 如果传进去一个string,那里面就不能对这个变量用减号-,因为string没有减法.(编译器可以发现这个错误,所以这样的代码是编译不过的)

    C++的max()等函数使用了这种方式,所以你会发现max()的两个参数必须相同.

    实例化

    在编译的时候,编译器会用具体的类型来代替类型模板参数,这个过程叫做实例化.

    其实就是生成指定了实际类型的函数,来替换模板函数.

    但是只会生成需要的类型,而不是每种类型都来一个.

    对于以上的那个模板函数,程序在编译的时候,会检查这个函数在代码中被传入了什么类型,然后对于每种用到的类型,生成一个函数来替换原来的模板函数.

    例如,如果程序中的main如下:

    int main()
    {
        fun((int)1, (int)2);
        fun((double)1.0, (double)2.0);
    }
    
    

    那么就只会生成int fun(int a, int b)double fun(double a, double b).

    使用多个类型

    你可以在模板函数里用多个类型,形状如下

    template <typename X, typename Y>
    void fun(X tv1, Y tv2)
    {
        cout << tv1 << ' ' << tv2 << endl;
    }
    

    这时,调用像这样fun(1, 2.0).

    手动指定类型

    但是使用多个类型的时候,编译器不一定能推测出到底是哪个对应什么类型,例如

    template <typename X, typename Y, typename Z>
    Z fun(X a, Y b)
    {
        return a*b;
    }
    
    

    如果你这样调用int tmp = fun(1, 2.0), 就会运行错误,因为编译器推测不出Z是什么类型.

    所以你应该在调用的时候,通过尖括号指定类型,像这样int tmp = fun<int, double, int>(1, 2.0).

    仅仅指定一部分类型

    其实我们可以只指定推测不出来的类型,而不指定能够推测的类型.

    要怎么做,我们可以把推测不出来的类型放到最前面,如下

    template <typename Z, typename X, typename Y>
    Z fun(X a, Y b)
    {
        return a*b;
    }
    
    

    那么我们可以这样调用int tmp = fun<int>(1, 2.0).

    尖括号里面只要写一个int,用来指定推测不出来的Z就好了.

    注意,一定要把需要指定的参数堆到最前面,不能跳着指定的.

    auto推断返回值

    很多时候,推测不出的是返回值,我们可以用auto代替返回值,形状如下

    template<typename X, typename Y>
    auto fun(X x, Y y)
    {
        return x*y;
    }
    
    

    返回类型后置语法

    有这样一种操作

    template<typename X, typename Y>
    auto fun(X x, Y y) -> decltype(x*y)
    {
        return x*y;
    }
    
    

    这里auto并没有进行类型推导.

    空函数列表的作用

    有时候一个模板函数本身已经有能力推测出所有类型了,我们没有必要再加尖括号.

    但如果存在一个同名的普通函数fun(int a, int b), 那么这样调用fun(1,2)的时候,就会优先调用普通函数.

    如果我们加一个尖括号fun<>(1, 2),虽然没有含义,但是可以让它调用模板函数.

  • 相关阅读:
    2020/11/4
    2020/11/10
    2020/11/12
    2020/11/5
    20201113 千锤百炼软工人
    20201112 千锤百炼软工人
    Java_swing_打开文件目录
    千锤百炼软工周报二
    9.29 课下动手动脑
    开学小测感想
  • 原文地址:https://www.cnblogs.com/zzidun-pavo/p/14269847.html
Copyright © 2011-2022 走看看