概述

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++)基本用法实践:四、模板的更多相关文章

  1. Linux中sed的用法实践

    Linux中sed的用法实践 参考资料:https://www.cnblogs.com/emanlee/archive/2013/09/07/3307642.html http://www.fn139 ...

  2. WebSocket原理与实践(四)--生成数据帧

    WebSocket原理与实践(四)--生成数据帧 从服务器发往客户端的数据也是同样的数据帧,但是从服务器发送到客户端的数据帧不需要掩码的.我们自己需要去生成数据帧,解析数据帧的时候我们需要分片. 消息 ...

  3. 【实践报告】Linux实践四

    Linux内核分析 实践四——ELF文件格式分析 一.概述 1.ELF全称Executable and Linkable Format,可执行连接格式,ELF格式的文件用于存储Linux程序.ELF文 ...

  4. Linux及安全实践四——ELF文件格式分析

    Linux及安全实践四——ELF文件格式分析 一.ELF文件格式概述 1. ELF:是一种对象文件的格式,用于定义不同类型的对象文件中都放了什么东西.以及都以什么样的格式去放这些东西. 二.分析一个E ...

  5. nodejs 实践:express 最佳实践(四) express-session 解析

    nodejs 实践:express 最佳实践(四) express-session 解析 nodejs 发展很快,从 npm 上面的包托管数量就可以看出来.不过从另一方面来看,也是反映了 nodejs ...

  6. Linux find命令的用法实践

    一.find命令简介 Linux下find命令在目录结构中搜索文件,并执行指定的操作.Linux下find命令提供了相当多的查找条件,功能很强大.由于find具有强大的功能,所以它的选项也很多,其中大 ...

  7. Android最佳性能实践(四)——布局优化技巧

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/43376527 在前面几篇文章其中.我们学习了怎样通过合理管理内存,以及高性能编码技 ...

  8. UWP开发之Mvvmlight实践四:{x:bind}和{Binding}区别详解

    {x:bind}是随着UWP被推出而被添加的,可以说是Win10 UWP开发专有扩展.虽然 {x:Bind} 缺少{Binding} 中的一些功能,但它运行时所花费的时间和使用的内存量均比 {Bind ...

  9. Linux课程实践四:ELF文件格式分析

    一.ELF文件格式概述 1. ELF文件 ELF:Executable and Linking Format,是一种对象文件的格式,用于定义不同类型的对象文件(Object files)中都放了什么东 ...

  10. AI (Adobe Illustrator)详细用法(四)

    本节主要是介绍和形状相关的操作. 一.外观面板的使用 熟悉外观面板的使用很重要. 1.新增描边 外观面板可以让我们增加多个描边. 点击“新增描边”,系统自动添加一个描边. 选中文字,新增描边,可以修改 ...

随机推荐

  1. Dokcer应用部署(搭建Wordpress网站)

    实现多个容器之间的协同,搭建Wordpress网站,要用到3个容器,Wordpress.MariaDB和Nginx 拉取镜像 使用docker pull拉取3个镜像: $ sudo docker pu ...

  2. AGC061 F Perfect String

    毒瘤出题人,史诗加强 AGC 的 F-- 然而我连原题都不会,所以只学了原题做法. 翻译一下题意就是给定一张循环网格图,求经过 \((0,0)\) 的闭合回路条数. 由于网格图中每一个位置都等价,所以 ...

  3. Kubernetes Gateway API 深入解读和落地指南

    背景 Kubernetes Gateway API 是 Kubernetes 1.18 版本引入的一种新的 API 规范,是 Kubernetes 官方正在开发的新的 API,Ingress 是 Ku ...

  4. React笔记-组件通信(六)

    React笔记-组件通信(六) props概念 props是组件之间通讯的纽带 props也是组件中内置的一个属性 通过父级组件传入 在类组件里 可以直接通过this.props获取 注意: prop ...

  5. 2022-11-22:小美将要期中考试,有n道题,对于第i道题, 小美有pi的几率做对,获得ai的分值,还有(1-pi)的概率做错,得0分。 小美总分是每道题获得的分数。 小美不甘于此,决定突击复习,

    2022-11-22:小美将要期中考试,有n道题,对于第i道题, 小美有pi的几率做对,获得ai的分值,还有(1-pi)的概率做错,得0分. 小美总分是每道题获得的分数. 小美不甘于此,决定突击复习, ...

  6. Django笔记四十之运行Django环境的python脚本

    本文首发于公众号:Hunter后端 原文链接:Django笔记四十之运行Django环境的python脚本 这一篇笔记介绍如何在 Django 中运行脚本. 假设说我们要实现一个功能,需要获取 blo ...

  7. Java中synchronized的优化

    本文介绍为了实现高效并发,虚拟机对 synchronized 做的一系列的锁优化措施 高效并发是从 JDK5 升级到 JDK6 后一项重要的改进项,HotSpot 虚拟机开发团队在 JDK6 这个版本 ...

  8. 避坑版-OpenSSH 用户名枚举漏洞(CVE-2018-15473)

    介绍: OpenSSH 7.7前存在一个用户名枚举漏洞,通过该漏洞,攻击者可以判断某个用户名是否存在于目标主机中,在复现过程中遇到了很多坑,这里我就把遇到坑和解决方法告诉大家!!! 漏洞环境: 靶机: ...

  9. odoo开发教程五:高级视图

    树视图 tree视图表现出来是列表视图,列表中一行一纪录.可以根据每行纪录的某字段值不同而把每行以不同样式显示. decoration-{样式}="条件" 样式主要有: bf(fo ...

  10. ping不通能curl通

    今天发现一个域名或ip居然在ping不通的情况下能curl通,以前的思维定式直接给整破防了啊!!! 涨见识了,具体原因和原理后续补充~