厦门建设网站哪家好,wordpress menu 插件,承德的网站建设公司,临沂品牌网站推广1. 模板函数与模板类
模板Template和函数重载是实现静态多态的两种重要途径。对于模板而言#xff0c;其通常用于模板函数和模板类中。其基本语法结构为#xff1a;
template typename XXXX // XXXX 代表定义的模板数据类型的名称1.1 模板函数
使用 template 关键…1. 模板函数与模板类
模板Template和函数重载是实现静态多态的两种重要途径。对于模板而言其通常用于模板函数和模板类中。其基本语法结构为
template typename XXXX // XXXX 代表定义的模板数据类型的名称1.1 模板函数
使用 template 关键字定义类型用定义好的新类型定义函数类型以及其参数类型。调用模板函数式方法函数名函数参数类型参数列表若实参并非该指定类型则先进行强制转换或者不显式说明函数参数类型由编译器自主推断此时输出参数的类型必须一致。
#includeiostream
using namespace std;// 1.1 模板函数
templatetypename ftype // 使用 template 关键字定义类型 可以同时定义多个类型
ftype myMax(ftype a, ftype b){ // 用定义好的新类型定义函数类型以及其参数类型return (a b) ? a : b;
}int main(){int a 10, b 15;int ans1 myMaxint(a, b); // 调用模板函数方法1函数名函数参数类型参数列表int ans2 myMax(a, b); // 调用目标函数方法2不显式说明函数参数类型由编译器自主推断cout ans1: ans1 endl;cout ans2: ans2 endl;
}1.2 模板类
类似于模板类使用 template 关键字定义类型可以同时定义多个类型然后就可以用定义好的新类型定义成员变量的函数类型类中构造函数/其他函数使用模板参数类型就类似于模板函数的使用方法。调用方法可以不显式说明函数参数类型由编译器自主推断也可以函数名函数参数类型参数列表若实参并非该指定类型则先进行强制转换。
#includeiostream
using namespace std;// 1.2 模板类
template typename ctype, typename btype // 使用 template 关键字定义类型可以同时定义多个类型
class myclass{public:ctype m_var1; // 用定义好的新类型定义成员变量的函数类型btype m_var2;myclass(ctype var1, btype var2) : m_var1(var1), m_var2(var2){ // 构造函数/其他函数类似于模板函数的使用方法cout m_var1: m_var1 endl;cout m_var2: m_var2 endl;};
};int main(){int a 10;float b 15;myclass cls1(a, b); // 调用方法1不显式说明函数参数类型由编译器自主推断myclassint, float cls2(a, b); // 调用模板函数方法2函数名函数参数类型参数列表若实参并非该指定类型则先进行强制转换
}1.3 模板特定化
类似于函数重载当我的同一个名字的类有多种不同的实现方法时我希望编译器能够根据我指定的类参数类型自动匹配对应的类实现方法时可以使用模板特定化的功能。以下展示 myclass 类的两种使用方法当指定类型为 char 类型时则编译器自动调用第二种类型即把小写字母转化为大写字母否则自动调用第一种类的实现方法即直接打印输出。
#includeiostream
using namespace std;// myclass 模板类的第一种实现方法
template typename ctype, typename btype // 使用 template 关键字定义类型可以同时定义多个类型
class myclass{ public:ctype m_var1; // 用定义好的新类型定义成员变量的函数类型btype m_var2;myclass(ctype var1, btype var2) : m_var1(var1), m_var2(var2){ // 构造函数/其他函数类似于模板函数的使用方法cout m_var1: m_var1 endl;cout m_var2: m_var2 endl;};
};// myclass 模板类的第二种实现方法
template
class myclasschar, char { // 类型为 char 型时调用
public:char first;char second;myclass(char first, char second) : first(first), second(second) {// Special behavior for characters (e.g., convert to uppercase)cout char(std::toupper(this-first)) endl; // 转化为大写cout char(std::toupper(this-second)) endl;};
};int main(){int a 10;float b 15;char c c, d d;myclassint, float cls2(a, b); // 调用 myclass 模板类的第一种实现方法 输出 m_var1: 10 m_var2: 15myclass cls1(c, d); // 调用 myclass 模板类的第二种实现方法输出 C D
}以上例子的第二种 myclass 的实现方法展示了如何使用全部模板特定化可以看到其基础的语法格式为
// 模板特定化定义方法
template // 内不设置任何的参数
class ClassName 基础类型1基础类型2{}当然除了全部模板特定化还可以只定义所有模板种的部分为特定的基础类型编译器也会根据部分匹配来优先选择合适的模板函数。其基础语法如下
// 部分模板特定化定义方法
// 例子1部分参数特定化
templatetypename T // 内设置自定义的参数类型
class ClassName T, char{}; // 带有 char 类型的变量自动调用该类
// 例子2部分指针特定化
templatetypename T // 内设置自定义的参数类型
class ClassName T*{}; // 指针变量则自动调用模板类2. 可变参数模板
首先什么场景需要用到可变参数模板呢如1.2中的例子我需要初始化两个参数所以我们模板函数的写法为
template typename ctype, typename btype // 使用 template 关键字定义类型可以同时定义多个类型当我需要初始50个或者未知个数的参数时这种方法就显得非常鸡肋了因此引入可变参数模板其基础语法为
template typename... Args // 其中 Args 代表参数类型的列表因为不确定模板参数类型的个数有多少因此常常通过递归调用的方法实现。以下通过一个函数和一个类展示其用法。
#includeiostream
using namespace std;// 2.1 可变参数模板函数
template typename T // base case当递归到最后一个元素时会调用该函数
T mysum(T t) {return t;
}template typename T, typename... ARGS // 可以适用于未知个数函数参数
T mysum(T t, ARGS... args){return t mysum(args...);
}// 2.2 可变参数模板类template typename... Types
class myclass;// 类似于函数也需要额外定义 base case即递归到空类
template
class myclass{};templatetypename Head, typename... Tail
class myclassHead, Tail... : public myclassTail...{public:myclass(Head head, Tail... tail) : myclassTail...(tail...), head_(head){cout head_ endl;};private:Head head_;
};int main(){cout mysum(1, 2, 3, 4, 5, 6) endl; // output: 21myclassint, float, double, int cls(1, 2.0f, 3.0, 4); // 当不显式设置参数类型时报错无法自动推断不解, output: 4, 3, 2, 1
}3. 类型特征与模板函数
函数特征通过头文件 #includetype_traits 添加。其核心功能在判断输入变量是否属于某一个特定的类型如
#includeiostream
#includetype_traits
using namespace std;int main(){int a 10;cout is it a pointer? boolalpha is_pointerdecltype(a)::value endl; // is it a pointer? falsecout is it a arithmetic? boolalpha is_arithmeticdecltype(a)::value endl; // is it a arithmetic? truecout is it a function? boolalpha is_functiondecltype(a)::value endl; // is it a function? false
}那么这如何跟模板函数梦幻联动呢通过 条件控制
std::conditionalcondition, A, B 如果条件为真则使用模板类型A否则使用类型Bstd::enable_ifcondition, A如果条件为真则使用模板类型A否则没有输入类型
#includeiostream
#includetype_traits
using namespace std;template typename T
typename enable_ifis_arithmeticT::value, T::type find_max(T a, T b){cout max value is: (a b ? a : b) endl;
};template typename T
typename conditionalis_arithmeticT::value, T, char::type find_max1(T a, T b){cout max value is: (a b ? a : b) endl;
}int main(){int a 10, b 25;find_max(a, b);find_max1(a, b);
}