当前位置: 首页 > news >正文

奇异递归Template有啥奇的?

如果一个模版看起来很头痛,那么大概率这种模版是用来炫技,没啥用的,但是CRTP这个模版,虽然看起来头大,但是却经常被端上桌~

奇异递归模板模式(Curiously Recurring Template Pattern, CRTP)是一种 C++ 模板编程技巧,用于实现静态多态。这种模式利用模板递归来允许一个类继承自一个模板类,其中模板参数是该类自身。这种模式可以用于各种用途,包括实现类型安全的单例模式、静态接口和性能优化。

CRTP基本概念

在 CRTP 模式中,一个类 Derived 继承自一个模板类 Base,这个模板类 Base 的模板参数是 Derived 自身。这样做的好处是允许在编译时确定 Derived 类型的信息,从而在不需要运行时多态的情况下实现多态行为。以下是 CRTP 的基本示例,展示了如何使用 CRTP 模式实现一个简单的静态接口:

#include <iostream>
using namespace std;template <typename Child>
struct Base
{
void interface()
{static_cast<Child*>(this)->implementation();
}
};struct Derived : Base<Derived>
{
void implementation()
{cout << "Derived implementation\n";
}
};int main()
{Derived d;d.interface();  // Prints "Derived implementation"return 0;
}

CRPT模板展开

遇到CRPT不要慌,一慌忘光光,为了认识这种代码的本质,我们不妨用Insights将其展开 , C++ Insights

#include <iostream>
using namespace std;template<typename Child>
struct Base
{inline void interface(){static_cast<Child *>(this)->implementation();}};/* First instantiated from: insights.cpp:13 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
struct Base<Derived>
{inline void interface(){static_cast<Derived *>(this)->implementation();}// inline constexpr Base() noexcept = default;
};#endifstruct Derived : public Base<Derived>
{inline void implementation(){std::operator<<(std::cerr, "Derived implementation\n");}// inline constexpr Derived() noexcept = default;
};int main()
{Derived d;static_cast<Base<Derived>&>(d).interface();return 0;
}

可以发现,展开的代码平平无奇,一目了然。

  • Base 类是一个模板类,它接受一个 Derived 类型作为模板参数。
  • Derived 类继承自 Base<Derived>,从而在 Base 中能够静态地调用 Derived 类中的方法。

另一个CRPT实例

以下是一个稍微复杂一点使用 CRTP 实现策略模式的例子:


#include <iostream>// CRTP 基类
template <typename Derived>
class Strategy {
public:
void execute() {// 调用 Derived 类中的实现static_cast<Derived*>(this)->perform();
}
};// 具体策略 1
class ConcreteStrategy1 : public Strategy<ConcreteStrategy1> {
public:
void perform() {std::cout << "ConcreteStrategy1 implementation" << std::endl;
}
};// 具体策略 2
class ConcreteStrategy2 : public Strategy<ConcreteStrategy2> {
public:
void perform() {std::cout << "ConcreteStrategy2 implementation" << std::endl;
}
};int main() {ConcreteStrategy1 s1;ConcreteStrategy2 s2;s1.execute(); // 输出 "ConcreteStrategy1 implementation"s2.execute(); // 输出 "ConcreteStrategy2 implementation"return 0;
}

在这个示例中,Strategy 是 CRTP 基类,它定义了一个 execute 方法,该方法调用派生类的 perform 方法。具体策略类 ConcreteStrategy1ConcreteStrategy2 实现了不同的 perform 方法。这样,Strategy 基类就能够静态地调用不同的策略实现。

总结

看到CRPT,第一眼应该想到,这玩意没什么特别的,就是为了实现静态多态的。

  • 静态体现在哪儿,都是模版函数,在编译期都已经展开,函数调用是写死的
  • 多态体现在哪儿,调佣基类的公用接口,最后会执行子类的具体实现,这一点和虚函数多态有点相似,但这种多态是静态的。

所以,CRPT就这点东西。

相关文章:

奇异递归Template有啥奇的?

如果一个模版看起来很头痛&#xff0c;那么大概率这种模版是用来炫技&#xff0c;没啥用的&#xff0c;但是CRTP这个模版&#xff0c;虽然看起来头大&#xff0c;但是却经常被端上桌~ 奇异递归模板模式&#xff08;Curiously Recurring Template Pattern, CRTP&#xff09;是一…...

每天五分钟深度学习框架pytorch:神经网络工具箱nn的介绍

本文重点 我们前面一章学习了自动求导,这很有用,但是在实际使用中我们基本不会使用,因为这个技术过于底层,我们接下来将学习pytorch中的nn模块,它是构建于autograd之上的神经网络模块,也就是说我们使用pytorch封装好的神经网络层,它自动会具有求导的功能,也就是说这部…...

【办公软件】安全风险 Microsoft 已阻止宏运行,因为此文件的来源不受信任

Excel 2019版本&#xff0c;就出现安全风险 Microsoft 已阻止宏运行 因为此文件的来源不受信任的问题&#xff0c;宏直接就用不了了。 网上的解决方法&#xff0c;文件右键属性->取消安全锁。但存在没有安全锁这个选项。后查询到一个简单的解决方法。 打开Excel表格->文件…...

JavaScript语法基础之流程结构(顺序、选择、循环结构)

目录 1. 流程控制 1.1. 流程控制简介 1.1.1. 顺序结构 1.1.2. 选择结构 1.1.3. 循环结构 1.2. 选择结构&#xff1a;if 1.2.1. 单向选择&#xff1a;if… 1.2.2. 双向选择&#xff1a;if…else… 1.2.3. 多向选择&#xff1a;if…else_if…else… 1.3. 选择结构&#…...

集团数字化转型方案(四)

集团数字化转型方案通过全面部署人工智能&#xff08;AI&#xff09;、大数据分析、云计算和物联网&#xff08;IoT&#xff09;技术&#xff0c;创建了一个智能化的企业运营平台&#xff0c;涵盖从业务流程自动化、实时数据监控、精准决策支持&#xff0c;到个性化客户服务和高…...

【MySQL索引】索引失效场景

索引失效 1 全值匹配肯定不失效 2 最佳左前缀法则 索引文件具有 B-Tree 的最左前缀匹配特性&#xff0c;如果左边的值未确定&#xff0c;那么无法使用此索引。 3 主键插入顺序 页分裂&#xff0c;建议 让主键具有 AUTO_INCREMENT 4 计算、函数、类型转换(自动或手动)导致…...

基于MATLAB视觉的静态手势识别系统

一、课题介绍及思路 为了丰富手势识别方法的多样性&#xff0c;提高手势识别的正确率&#xff0c;提出了一种基于手势轮廓像素变化的手势识别方法。在Matlab环境下&#xff0c;设计并开发了一个基于视觉的静态手势识别系统。系统主要由两部分组成&#xff1a;手势分割与手势识…...

day02-作业题

一、简答题 请说出方法定义的全格式 访问修饰符 静态修饰符 返回值 方法名(参数列表){方法体;retrun 返回值;}请说出方法重载的概念 在一个类中&#xff0c;可以定义方法名相同&#xff0c;参数列表不相同(参数类型、参数个数或者参数顺序不同)的方法请简述什么是类&#xf…...

torch.cuda.set_divice()

我申请了两块GPU,然后看两张显卡的编号 import torch torch.cuda.set_device(0) # 设置当前cuda设备编号为1 print("当前cuda设备是", torch.cuda.current_device()) # 获取当前cuda设备import torch torch.cuda.set_device(1) …...

<数据集>RSOD数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;936张 标注数量(xml文件个数)&#xff1a;936 标注数量(txt文件个数)&#xff1a;936 标注类别数&#xff1a;4 标注类别名称&#xff1a;[aircraft, oiltank, overpass, playground] 序号类别名称图片数框数1air…...

企业高性能web服务器之Nginx

文章目录 Apache经典的web服务端Apache prefork 模型Apache work 模型&#xff08;适应市场&#xff09;Apache event 模型 网络I/O网络I/O模型I/O模型网络I/O模型 Nginx架构和安装Nginx源码编译环境准备安装nginx Nginx的平滑升级及版本回滚 Nginx架构和进程Nginx进程结构Ngin…...

11-sentinel利用nacos作持久化

本文介绍sentinel配置数据的持久化方法。由于sentinel官方并没有提供持久化功能&#xff0c;大家在测试过程中也能发现sentinel服务重启后&#xff0c;原来配置的数据就丢了&#xff0c;本文就是来处理这一问题的。 做好心理准备&#xff0c;我们要修改sentinel的源代码&#…...

密码学之哈希算法

文章目录 1. 哈希函数概述1.1 哈希函数的定义1.2 哈希函数的重要性 2. SHA系列算法简介2.1 SHA系列的发展历史2.2 SHA系列的应用场景 3. 主要SHA算法详解3.1 MD5算法3.2 SHA-1算法3.3 SHA-2算法家族3.4 SHA-3算法 4. SHA算法的安全性分析4.1 安全性的重要性4.2 已知的攻击方法4…...

杰发科技AC7801——GPIO通过寄存器地址控制高低电平

通过这个寄存器来查看控制的是哪个ODR值&#xff0c;使用sample&#xff0c;发现是0x20080068的第7和第9位 使用51控制寄存器的代码来置高置低代码&#xff0c;注意变量需要用unsigned int来声明 unsigned int ledBit 0;mdelay(100);ledBit | (1 << 9); ledBit & ~…...

代码随想录算法训练营第三十一天| 01背包问题 二维 01背包问题 一维 416. 分割等和子集

01背包问题 二维 代码随想录 视频讲解&#xff1a;带你学透0-1背包问题&#xff01;| 关于背包问题&#xff0c;你不清楚的地方&#xff0c;这里都讲了&#xff01;| 动态规划经典问题 | 数据结构与算法_哔哩哔哩_bilibili #include <bits/stdc.h> using namespace std;…...

github删除历史所有commit

背景 注意非确认情况下最好不要此操作 由于不小心在某些commits中提交了敏感信息&#xff0c;需要删除这些commits记录 网上看了很多方法&#xff0c;都是根据commit 找到一条id然后全部清除得&#xff0c;因为我是需要全部删除&#xff0c;所以有一种更简单得思路。 过程 1…...

C++前向声明简介

前向声明 class a; class b; class c:public d { ..... }类a和b已经实现了具体功能&#xff0c;类c在定义&#xff0c;在类c上面声明类a和b有什么作用 在类 c 的定义上面声明类 a 和 b 的作用主要是为了确保在编译时能够识别这两个类的存在&#xff0c;特别是在类 c 中可能会使…...

华为手机是越贵越好吗?

华为手机的价格与其性能、功能、设计以及市场定位等多种因素有关&#xff0c;因此不能简单地说华为手机越贵就越好。 首先&#xff0c;华为手机的产品线非常广泛&#xff0c;涵盖了从入门级到旗舰级的多个系列&#xff0c;每个系列都有其特定的目标用户群和市场需求。因此&…...

【java基础】IDEA 的断点调试(Debug)

目录 1.为什么需要 Debug 2.Debug的步骤 2.1添加断点 2.2单步调试工具介绍 2.2.1 Step Over 2.2.2 Step Into 2.2.3 Force Step Into 2.2.4 Step Out 2.2.5 Run To Cursor 2.2.6 Show Execution Poiint 2.2.7 Resume Program 3.多种 Debug 情况介绍 3.1行断点 3.2方…...

MPLS相关实验

一、实验拓扑图以及实验要求 1、实验拓扑图 2、实验要求 合理利用IP地址进行分配R3、R4、R5、R6运行ospf在R2、R3、R4、R5、R6上运行MPLSR1上使用静态&#xff0c;R7上运行rip协议&#xff0c;R8上运行ospf协议全网可达 二、实验分析 合理利用IP地址进行分配R3、R4、R5、R6…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...