1)普通类的成员函数模板
class A
{
public:template<typename T> //类的成员函数模板,//成员函数模板和函数模板长得样子一样!void func(T tmp);
};template<typename T>
void A::func(T tmp)
{cout << tmp << endl;
}int main()
{A a;a.func<double>(56.89);return 0;
}
2)模板类的成员函数模板
template<class T2>
class A
{
public:A(T2 arg):arg_(arg){}template<typename T> //类的成员函数模板void func(T tmp);
private:T2 arg_;
};//模板类的成员函数模板类外定义方法
template<class T2>
template<typename T>
void A<T2>::func(T tmp)
{cout << tmp + arg_ << endl;
}int main()
{A<int> a1(45);a1.func<int>(45); //output 90return 0;
}
3)模板显式实例化,显式声明
显式实例化作用:为了防止多个.cpp文件生成相同的类模板,较少系统编译的开销;
实例化定义,实例化声明!
template A; //在多个.cpp文件中的其中任意一个文件中,实例化定义【只有一个】
extern template A; //在其他.cpp文件中,实例化声明【可以有多个】, 代表此文件不用在实例化
4)using定义模板别名(下面案例是定义map容器的类模板别名)
//using str_map_t = std::map<std::string, T> type;
//上面这句话,既不是函数模板,也不是类模板,是用using定义一个类型别名,也叫【类型模板】;
template<class T>
using str_map_t = std::map<std::string, T>; //类型模板,也叫模板别名int main()
{str_map_t<int> m1;m1.insert({"abc",123});return 0;
}
4.1)用typedef在模板类中,重新定义新的类型,但无法重新定义一个模板!!!using可以,定义的名字叫类型模板;
template //C++98之前的写法
struct A
{
typedef std::map<string, T> mapType; //必须有typedef,否则会编译错误
};
int main()
{
A::mapType a1;
a1.insert({ “first”,23 });
return 0;
}
//typedef int myint_t; //用typedef定义别名,就好像定义一个变量一样!!!
typedef int(func)(int, int);
using funcptr = int()(int, int); //有using定义一个函数指针的写法
5)显示指定模板参数
template<class T1,class T2,class T3>
T1 func(T2 a, T3 b)
{return a + b;
}int main()
{//auto ret = func(3, 6);这样写不行,因为T1没有类型,必须显示指定;auto ret = func<int>(3, 6);cout << ret << endl;return 0;
}
6)类模板全特化
说明:必须有泛化版本,才可以有特化版本!!!特化版本优先被编译;template<class T> //泛化版本
class A
{
public:bool compare(const T& tmp){cout << "一般模板" << tmp << endl;if (tmp > 2.5) return 1;}
};template<>
class A<float> //全特化版本,注意float绑定到类A上,注意写法!!!
{
public:bool compare(const float& tmp){cout << "全特化" <<tmp << endl;if (tmp > 2.5) return 1;}
};int main()
{A<float> a;a.compare(4.7); //调用全特化版本A<int> a2;a2.compare(40); //泛化版本return 0;
}
7)特化成员函数而不是模板
注意:特化成员函数就一个类,这是跟模板类特化的重要区别!!!
class A
{
public:template<typename T>void func(T tmp);
};template<typename T> //成员函数的泛化版本
void A::func(T tmp)
{cout << "成员函数的泛化版本 " << tmp << endl;
}template<> //成员函数的特化版本
void A::func(int tmp)
{cout << "成员函数的特化版本 " << tmp << endl;
}int main()
{A a;a.func<>(6); //调用的是特化版本a.func<float>(5.3); //调用的是泛化版本return 0;
}
8)类模板偏特化(也就局部特化)
//偏特化两方面:1)从模板参数数量上;2)模板参数范围上
template<class T,class U,class W>
class A //泛化类模板
{
public:A() { cout << "泛化版本 A constructor" << endl; }void func(void){ cout << "泛化版本 func" << endl; }
};template<class U,class W>
class A<int,U,W>
{
public:A() { cout << "偏特化版本1 A constructor" << endl; }void func(void) { cout << "偏特化版本1 func" << endl; }
};template<class T, class W>
class A<T, float, W>
{
public:A() { cout << "偏特化版本2 A constructor" << endl; }void func(void) { cout << "偏特化版本2 func" << endl; }
};int main()
{A<char,int,int> a1; a1.func();//调用的是泛化版本A<int, int, int> a2;a2.func();//调用的是特化版本1return 0;
}
9)函数模板全特化,函数模板没有偏特化
template<typename T,typename U>
void func(T a, U b)
{cout << "函数模板泛化 " << a + b << endl;
}//以下5句代码用于不会执行!!!
template<typename T>
void func<T, double>(T a, double b) //函数模板偏特化,这是不可以的,编译不过去!!!!!!!!
{cout <<"函数模板偏特化--------------- "<< a + b << endl;
}template<>
void func<double,double>(double a, double b) //必须有“<double,double>”,如果没有,则本质上是函数重载;
{cout << "函数模板全特化--- " << a + b << endl;
}int main()
{func<int,int>(3, 4.7); //调用的是泛化版本func<int,double>(4, 2.7);func<>(3.4, 5.6);//调用的是全特化版本return 0;
}