C++基本用法实践之模板详解
作者:寡人正在Coding
C++的模板是泛型编程思想的一种实现,模板不光支持函数模板,还有类模板等,本文主要来和大家聊聊C++中模板的相关用法,需要的可以参考一下
概述
C++的模板是泛型编程思想的一种实现。C++是强类型语言,处处强调类型。同样的加法运算,int和float的加法运算需定义两个函数(重载),而使用模板则可以只用一个函数(见下面示例)。
这类似我们面向对象所说的多态(定义加法运算,各个类型有不同的实现),所以是所谓静多态的一种实现方式,不同的是,模板在编译期展开生成int和float两个加法函数,如:
template<class T> T add(T a, T b) { return a + b; } int v1 = add<int>(1, 2); // 不显式声明模板参数类型,编译器会试图推断 float v2 = add(1.5f, 2.5f); /* 实际上编译器生成了两个函数 int add<int>(int a, int b) float add<float>(float a, float b) */
模板不光支持函数模板,还有类模板等,思想是一样的(详情见下面例子)。
模板还有一些特性机制如:模板特化,SFINAE(substitution failure is not an error 替换而非错误),变长参数模板等,另外模板在元编程中也是十分重要的组成部分,我对元编程没有太多实践,读者有兴趣可以自行搜索。
用法举例
参考测试项目ModernCppTest/modrenc_template.cpp
主要内容:
- 函数模板&Lambda函数模板
- 类模板
- 别名模板
- 变量模板
- 值(枚举)作为模板参数(其实int类型也可以)
- 模板特化
- 变长参数模板
- 模板函数的完美转发
#include "ModernCppTestHeader.h" namespace n_template{ template <class T> void template_func(T t) { LOG_VAR(t); } template <class T> class Number { public: T v; Number(T v) : v(v) { LOG_VAR(v); } }; template <class T> constexpr T pi = T(3.1415926f); template <int INTVAL> void log_template_int_value() { LOG_VAR(INTVAL); } enum class EAnim : int { Other = 0, Cat = 1, Dog = 2, }; template<EAnim Ty> class Anim { public: void Bark() { LOG("默认:动物叫"); } }; template<> class Anim<EAnim::Dog> { public: void Bark() { LOG("狗:汪汪!"); } }; template<> class Anim<EAnim::Cat> { public: void Bark() { LOG("猫:喵喵!"); } }; // 注意递归基 void log_values() { LOG("展开结束"); } template<class T, class... ARGS> void log_values(T value, ARGS... args) { LOG(value); log_values(args...); } template<class T> void func_plus(T&& a) { auto v = a; LOG("func_plus v = " << a); } template<class T, class... ARGS> void func_plus(T&& a, T&& b, ARGS... args) { func_plus(a + b, std::forward<ARGS>(args)...); } template<class T> void func_mul(T&& a) { auto v = a; LOG("func_mul v = " << a); } template<class T, class... ARGS> void func_mul(T&& a, T&& b, ARGS... args) { func_mul(a + b, std::forward<ARGS>(args)...); } template <class... ARGS> void call_func(const std::string& name, ARGS&&... args) { if (name == "plus") func_plus(std::forward<ARGS>(args)...); else if (name == "mul") func_mul(std::forward<ARGS>(args)...); else LOG("Unknown function name: " << name); } } template<typename T> using Num = n_template::Number<T>; void template_test() { LOG_FUNC(); LOG_TAG(" 函数模板 "); { n_template::template_func(1); n_template::template_func(1.25f); LOG("Lambda 函数模板"); auto f = []<class T> (T t) { LOG_VAR(t); }; f(1); f(1.25f); } LOG_TAG("类模板"); { n_template::Number(1); n_template::Number(1.25f); } LOG_TAG("别名模板"); { Num<int>(1); Num<float>(1.25f); } LOG_TAG("变量模板"); { auto v1 = n_template::pi<int>; auto v2 = n_template::pi<float>; LOG_VAR(v1); LOG_VAR(v2); n_template::log_template_int_value<10>(); n_template::log_template_int_value<20>(); } LOG_TAG("枚举变量模板&模板特化"); { n_template::Anim<n_template::EAnim::Dog>().Bark(); n_template::Anim<n_template::EAnim::Cat>().Bark(); LOG("EAnim::Other 没有特化使用默认模板"); n_template::Anim<n_template::EAnim::Other>().Bark(); } LOG_TAG("变长参数模板"); { n_template::log_values("jack", 10, 3.14f); } LOG_TAG("变长参数模板的完美转发"); { n_template::call_func("plus", 1, 2, 3, 4); n_template::call_func("mul", 2, 3); } }
到此这篇关于C++基本用法实践之模板详解的文章就介绍到这了,更多相关C++模板内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!