第一章 函数模板

1.什么是函数模板?

函数模板是通过模板来实现family function,模板参数的类型可以是任意的。    

2.怎么使用模板

1.使用模板时,模板参数或类型会被替换,该过程称为实例化。
2.注意,模板类型可以为void*
3.模板编译过程分为两个步骤
    1.检测是否有语法错误,是否有使用未知的参数,静态断言不依赖于模板参数的
    2.实例化,该过程会再次检查所有参数
举一个例子:
     template<typename T>
     void foo(T t){
         declare();//第一次会检查declare是否存在(也就是是否合法)
         declare(t);//第二次检查declare是否合法,同时检查参数是否合法
         static_assert(sizeof(t)>10);//只会在实例化阶段检查是否合法
         static_assert(sizeof(int)>10);//第一次就会检查是否合法
     }

注意:1.有些编译器不会严格执行这个检查规范,目前知道msvc和gdb是遵守的

3.模板参数推导

    template<typename T>T max(T const&a,T const&b){
        return a<b?a;b;
    }
    template<typename T> void deduction(T a){
    }

1.对于max函数,如果实例化为max(1,2);那么T的类型将会被推到为int。

2.对于deduction函数而言,将会出现类型退化的特征(参数类型为值)特征如下:

int a;
int b[10];
int &d=a;
int &&c = std::move(a);
deduction(&a);//T type int*
deduction(a);//T type int
deduction(b);//T type int*
deduction(c);//T type int
deduction(d);//T type int

4.默认参数推导

     template<typename T>void foo(T = ""){
     }
     foo(1) //ok!

5.多参数模板

1.和前面的例子一样

template<typename T1,typename T2>void f(T1 a,T2 b){
}

2.可能遇到的问题

template<typename T1,typename T2>T1 max(T1 a,T2 b){
    return a>b?a:b;
}

可能已经注意到,如果我调用max(1,2.5),返回的会是2(小数转换为整数会向下取整);那么应该怎么解决这个问题呢?

3.解决问题

1.新增一个参数判断返回值

template<typename T3,typename T1,typename T2>T3 max(T1 a,T2 b){
    return a>b?a:b;
}
调用方式 max<double,int,double>(2,2.5); //太麻烦了!
或者调用 max<double>(2,2.5);//依然有点麻烦!

2.让编译器自动判断返回值

//这种写法要是c++14之后
template<typename T1,typename T2>auto max(T1 a,T2 b){
    return a>b?a:b; //很方便!
}
//c++14之前
template<typename T1,typename T2>auto max(T1 a,T2 b)->decltype(a>b?a:b){
    return a>b?a:b;
}

3.返回一个common_type_t

#include <type_traits>
template<typename A,typename B>std::common_type_t max(A a,B b){
    return a>b?a:b;
}

6.默认参数

    template<typename T,typename T1,typename RT = std::decay_t<std::decltype(true?a:b)>>//注意:decay防止返回引用
    RT max(T a,T1 b){
        return a>b?a:b;
    }

7.优先匹配

template<typename T> void func(T t) {
}
template<typename T>void func(T* t) {
}
int a = 10;
func(&a)//对于这个调用会优先匹配T*的函数

8.关于constexpr,自c++11之后,使编译期的计算成为可能

template<typename T> constexpr auto array(T t){
    return t;
}
int a[array(10)];//正确