现代C++(Modern 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++(Modern C++)基本用法实践:四、模板的更多相关文章
- Linux中sed的用法实践
Linux中sed的用法实践 参考资料:https://www.cnblogs.com/emanlee/archive/2013/09/07/3307642.html http://www.fn139 ...
- WebSocket原理与实践(四)--生成数据帧
WebSocket原理与实践(四)--生成数据帧 从服务器发往客户端的数据也是同样的数据帧,但是从服务器发送到客户端的数据帧不需要掩码的.我们自己需要去生成数据帧,解析数据帧的时候我们需要分片. 消息 ...
- 【实践报告】Linux实践四
Linux内核分析 实践四——ELF文件格式分析 一.概述 1.ELF全称Executable and Linkable Format,可执行连接格式,ELF格式的文件用于存储Linux程序.ELF文 ...
- Linux及安全实践四——ELF文件格式分析
Linux及安全实践四——ELF文件格式分析 一.ELF文件格式概述 1. ELF:是一种对象文件的格式,用于定义不同类型的对象文件中都放了什么东西.以及都以什么样的格式去放这些东西. 二.分析一个E ...
- nodejs 实践:express 最佳实践(四) express-session 解析
nodejs 实践:express 最佳实践(四) express-session 解析 nodejs 发展很快,从 npm 上面的包托管数量就可以看出来.不过从另一方面来看,也是反映了 nodejs ...
- Linux find命令的用法实践
一.find命令简介 Linux下find命令在目录结构中搜索文件,并执行指定的操作.Linux下find命令提供了相当多的查找条件,功能很强大.由于find具有强大的功能,所以它的选项也很多,其中大 ...
- Android最佳性能实践(四)——布局优化技巧
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/43376527 在前面几篇文章其中.我们学习了怎样通过合理管理内存,以及高性能编码技 ...
- UWP开发之Mvvmlight实践四:{x:bind}和{Binding}区别详解
{x:bind}是随着UWP被推出而被添加的,可以说是Win10 UWP开发专有扩展.虽然 {x:Bind} 缺少{Binding} 中的一些功能,但它运行时所花费的时间和使用的内存量均比 {Bind ...
- Linux课程实践四:ELF文件格式分析
一.ELF文件格式概述 1. ELF文件 ELF:Executable and Linking Format,是一种对象文件的格式,用于定义不同类型的对象文件(Object files)中都放了什么东 ...
- AI (Adobe Illustrator)详细用法(四)
本节主要是介绍和形状相关的操作. 一.外观面板的使用 熟悉外观面板的使用很重要. 1.新增描边 外观面板可以让我们增加多个描边. 点击“新增描边”,系统自动添加一个描边. 选中文字,新增描边,可以修改 ...
随机推荐
- Dokcer应用部署(搭建Wordpress网站)
实现多个容器之间的协同,搭建Wordpress网站,要用到3个容器,Wordpress.MariaDB和Nginx 拉取镜像 使用docker pull拉取3个镜像: $ sudo docker pu ...
- AGC061 F Perfect String
毒瘤出题人,史诗加强 AGC 的 F-- 然而我连原题都不会,所以只学了原题做法. 翻译一下题意就是给定一张循环网格图,求经过 \((0,0)\) 的闭合回路条数. 由于网格图中每一个位置都等价,所以 ...
- Kubernetes Gateway API 深入解读和落地指南
背景 Kubernetes Gateway API 是 Kubernetes 1.18 版本引入的一种新的 API 规范,是 Kubernetes 官方正在开发的新的 API,Ingress 是 Ku ...
- React笔记-组件通信(六)
React笔记-组件通信(六) props概念 props是组件之间通讯的纽带 props也是组件中内置的一个属性 通过父级组件传入 在类组件里 可以直接通过this.props获取 注意: prop ...
- 2022-11-22:小美将要期中考试,有n道题,对于第i道题, 小美有pi的几率做对,获得ai的分值,还有(1-pi)的概率做错,得0分。 小美总分是每道题获得的分数。 小美不甘于此,决定突击复习,
2022-11-22:小美将要期中考试,有n道题,对于第i道题, 小美有pi的几率做对,获得ai的分值,还有(1-pi)的概率做错,得0分. 小美总分是每道题获得的分数. 小美不甘于此,决定突击复习, ...
- Django笔记四十之运行Django环境的python脚本
本文首发于公众号:Hunter后端 原文链接:Django笔记四十之运行Django环境的python脚本 这一篇笔记介绍如何在 Django 中运行脚本. 假设说我们要实现一个功能,需要获取 blo ...
- Java中synchronized的优化
本文介绍为了实现高效并发,虚拟机对 synchronized 做的一系列的锁优化措施 高效并发是从 JDK5 升级到 JDK6 后一项重要的改进项,HotSpot 虚拟机开发团队在 JDK6 这个版本 ...
- 避坑版-OpenSSH 用户名枚举漏洞(CVE-2018-15473)
介绍: OpenSSH 7.7前存在一个用户名枚举漏洞,通过该漏洞,攻击者可以判断某个用户名是否存在于目标主机中,在复现过程中遇到了很多坑,这里我就把遇到坑和解决方法告诉大家!!! 漏洞环境: 靶机: ...
- odoo开发教程五:高级视图
树视图 tree视图表现出来是列表视图,列表中一行一纪录.可以根据每行纪录的某字段值不同而把每行以不同样式显示. decoration-{样式}="条件" 样式主要有: bf(fo ...
- ping不通能curl通
今天发现一个域名或ip居然在ping不通的情况下能curl通,以前的思维定式直接给整破防了啊!!! 涨见识了,具体原因和原理后续补充~