奇异递归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
方法。具体策略类 ConcreteStrategy1
和 ConcreteStrategy2
实现了不同的 perform
方法。这样,Strategy
基类就能够静态地调用不同的策略实现。
总结
看到CRPT,第一眼应该想到,这玩意没什么特别的,就是为了实现静态多态的。
- 静态体现在哪儿,都是模版函数,在编译期都已经展开,函数调用是写死的
- 多态体现在哪儿,调佣基类的公用接口,最后会执行子类的具体实现,这一点和虚函数多态有点相似,但这种多态是静态的。
所以,CRPT就这点东西。
相关文章:
奇异递归Template有啥奇的?
如果一个模版看起来很头痛,那么大概率这种模版是用来炫技,没啥用的,但是CRTP这个模版,虽然看起来头大,但是却经常被端上桌~ 奇异递归模板模式(Curiously Recurring Template Pattern, CRTP)是一…...

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

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

JavaScript语法基础之流程结构(顺序、选择、循环结构)
目录 1. 流程控制 1.1. 流程控制简介 1.1.1. 顺序结构 1.1.2. 选择结构 1.1.3. 循环结构 1.2. 选择结构:if 1.2.1. 单向选择:if… 1.2.2. 双向选择:if…else… 1.2.3. 多向选择:if…else_if…else… 1.3. 选择结构&#…...

集团数字化转型方案(四)
集团数字化转型方案通过全面部署人工智能(AI)、大数据分析、云计算和物联网(IoT)技术,创建了一个智能化的企业运营平台,涵盖从业务流程自动化、实时数据监控、精准决策支持,到个性化客户服务和高…...
【MySQL索引】索引失效场景
索引失效 1 全值匹配肯定不失效 2 最佳左前缀法则 索引文件具有 B-Tree 的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。 3 主键插入顺序 页分裂,建议 让主键具有 AUTO_INCREMENT 4 计算、函数、类型转换(自动或手动)导致…...

基于MATLAB视觉的静态手势识别系统
一、课题介绍及思路 为了丰富手势识别方法的多样性,提高手势识别的正确率,提出了一种基于手势轮廓像素变化的手势识别方法。在Matlab环境下,设计并开发了一个基于视觉的静态手势识别系统。系统主要由两部分组成:手势分割与手势识…...
day02-作业题
一、简答题 请说出方法定义的全格式 访问修饰符 静态修饰符 返回值 方法名(参数列表){方法体;retrun 返回值;}请说出方法重载的概念 在一个类中,可以定义方法名相同,参数列表不相同(参数类型、参数个数或者参数顺序不同)的方法请简述什么是类…...

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数据集<目标检测>
数据集格式:VOCYOLO格式 图片数量:936张 标注数量(xml文件个数):936 标注数量(txt文件个数):936 标注类别数:4 标注类别名称:[aircraft, oiltank, overpass, playground] 序号类别名称图片数框数1air…...

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

11-sentinel利用nacos作持久化
本文介绍sentinel配置数据的持久化方法。由于sentinel官方并没有提供持久化功能,大家在测试过程中也能发现sentinel服务重启后,原来配置的数据就丢了,本文就是来处理这一问题的。 做好心理准备,我们要修改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值,使用sample,发现是0x20080068的第7和第9位 使用51控制寄存器的代码来置高置低代码,注意变量需要用unsigned int来声明 unsigned int ledBit 0;mdelay(100);ledBit | (1 << 9); ledBit & ~…...
代码随想录算法训练营第三十一天| 01背包问题 二维 01背包问题 一维 416. 分割等和子集
01背包问题 二维 代码随想录 视频讲解:带你学透0-1背包问题!| 关于背包问题,你不清楚的地方,这里都讲了!| 动态规划经典问题 | 数据结构与算法_哔哩哔哩_bilibili #include <bits/stdc.h> using namespace std;…...
github删除历史所有commit
背景 注意非确认情况下最好不要此操作 由于不小心在某些commits中提交了敏感信息,需要删除这些commits记录 网上看了很多方法,都是根据commit 找到一条id然后全部清除得,因为我是需要全部删除,所以有一种更简单得思路。 过程 1…...
C++前向声明简介
前向声明 class a; class b; class c:public d { ..... }类a和b已经实现了具体功能,类c在定义,在类c上面声明类a和b有什么作用 在类 c 的定义上面声明类 a 和 b 的作用主要是为了确保在编译时能够识别这两个类的存在,特别是在类 c 中可能会使…...
华为手机是越贵越好吗?
华为手机的价格与其性能、功能、设计以及市场定位等多种因素有关,因此不能简单地说华为手机越贵就越好。 首先,华为手机的产品线非常广泛,涵盖了从入门级到旗舰级的多个系列,每个系列都有其特定的目标用户群和市场需求。因此&…...

【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上使用静态,R7上运行rip协议,R8上运行ospf协议全网可达 二、实验分析 合理利用IP地址进行分配R3、R4、R5、R6…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...

自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...