c++ 模板技巧——类型萃取
//traits.h/*制定输入 - 输出类型规则*/
template <class T>
struct RtnType {typedef T return_type;//默认返回类型和输入类型一致
};template <class T>
struct RtnType<T*> {//特化,当输入的是指针类型,返回类型规定为指针原型typedef T return_type;
};template <class T>
struct RtnType<const T*> {//特化常量指针类型,当输入的是常量指针类型,返回类型规定为原型指针typedef T* return_type;
};// 你可以根据需要,特化不同的输入输出规则/*特性萃取器*/
template <class unknown_class>
struct unknown_class_traits {typedef typename unknown_class::return_type return_type;
};/*特性萃取器 —— 针对指针*/
template <class T>
struct unknown_class_traits<T*> {typedef T return_type;
};/*特性萃取其 —— 针对常量指针*/
template <class T>
struct unknown_class_traits<const T*> {typedef const T return_type;
};#define RType typename unknown_class_traits<RtnType<T>>::return_type/*决定使用哪一个类型*/
template <class T>
inline RType return_type(T) {return RType();
}/*用户统一接口*/
template <class T>
inline RType interface(T param)
{const type_info& Rtid = typeid(RType);const type_info& Tid = typeid(T);const char* Rname = Rtid.name();const char* Tname = Tid.name();bool bRet = compare_type(param, RType());//return implement(param, RType());//static dispatch here. 编译期静态分发
}/*接口默认实现*/
template <class T>
inline RType implement(T param, RType typ)
{cout << "General Version of implement" << endl;return RType();
}template <class T, T Val>
struct var_constant
{const T value = Val;using value_type = T;using type = var_constant;
};template <bool Val>
struct var_constant<bool, Val>//特化bool类型
{const bool value = Val;using value_type = bool;using type = var_constant;
};template<class T1, class T2>
struct is_same_type
{static const bool value = false;
};template<class T>
struct is_same_type<T, T>
{static const bool value = true;
};template<class T1, class T2>
inline bool compare_type(T1, T2)
{var_constant<bool, is_same_type<T1, T2>::value> bConstant;return bConstant.value;
};
//main.cpp
#include "traits.h"class A
{};struct B
{};A implement(A, A)
{cout << "use object value type version" << endl;return A();
}B implement(B*, B)
{cout << "use object raw ptr type version" << endl;return B();
}int implement(int, int)
{cout << "use raw type version." << endl;return 0;
}int implement(int*, int)
{cout << "use raw ptr version." << endl;return 0;
}int* implement(const int*, int*)
{cout << "use const raw ptr version." << endl;return 0;
}int main() {B b;A a;int value = 1;int *p = &value;const int* cp = p;A v1 = interface(a);B v2 = interface(&b);int v3 = interface(p);int* v4 = interface(cp);char ch = getchar();return 0;
}
通过一些模板技巧,使得模块内部可以根据用户输入数据类型,返回不同的数据,实现接口的统一,并在接口内实现静态分发。
另一种基于模板的静态分发,可以采用CRTP,以下是基于CRTP技术实现编译期多态的例子,仅供参考:
template<class T>
class BaseObj
{
public:inline void Interface(){return static_cast<T*>(this)->Implement();}inline void Implement(){}~BaseObj() {static_cast<T*>(this)->Destory();}inline void Destory(){}
protected:// T m_subObj;// error. 基类中不能用子类来创建成员变量,这也是c++基本要求
};class Drive :public BaseObj<Drive>
{
public:Drive() {m_handle = new int[4];}//void Implement()//解开注释,观察效果,//{// printf("Drive Implement.\r\n");//}~Drive() {printf("Drive Deconstructed.\r\n");//Don't do any clear operation, put these into Destory call}void Destory(){printf("Drive Destoryed.\r\n");delete[] m_handle;m_handle = nullptr;//important 防止Destory被重复调用导致重复释放}
private:int* m_handle;
};// 使用CRTP技术创建的不同子类对象,由于基类都是不一样的,因此不能统一放入容器中使用,可以用std::Any类型对它们进行一层包装,这样就可以放进容器了(参考:https://blog.csdn.net/yuanshenqiang/article/details/143984861)。int main()
{Drive* d1 = new Drive;BaseObj<Drive>* dd1 = new Drive;dd1->Interface();d1->Interface();delete dd1;//d1->Destory();//手动调用Destorydelete d1;//由基类的析构函数发起Destory调用return 0;
}
相比而言动态分发就是常规的虚函数——继承体系,基于该体系,可以实现各种设计模式。比如一个有趣的例子:c++的二次分发与访问者模式-CSDN博客
相关文章:
c++ 模板技巧——类型萃取
//traits.h/*制定输入 - 输出类型规则*/ template <class T> struct RtnType {typedef T return_type;//默认返回类型和输入类型一致 };template <class T> struct RtnType<T*> {//特化,当输入的是指针类型,返回类型规定为指针原型typ…...

初步尝试AI应用开发平台——Dify的本地部署和应用开发
随着大语言模型LLM和相关应用的流行,在本地部署并构建知识库,结合企业的行业经验或个人的知识积累进行定制化开发,是LLM的一个重点发展方向,在此方向上也涌现出了众多软件框架和工具集,Dify就是其中广受关注的一款&…...

卷积神经网络中的局部卷积:原理、对比与应用解析
【内容摘要】 本文聚焦卷积神经网络中的局部卷积,重点解析全连接、局部连接、全卷积与局部卷积四种连接方式的差异,结合人脸识别任务案例,阐述局部卷积的应用场景及优势,为理解卷积网络连接机制提供技术参考。 关键词:…...

重拾童年,用 CodeBuddy 做自己的快乐创作者
某个炎炎的夏日午后,阳光透过稀疏的树叶洒落在地上,一道道光影斑驳陆离。那时候的我们,还只是三五个小朋友,蹲坐在村头的一棵老槐树下,手里握着并不属于自己的游戏掌机,轮流按动着手柄的按键,在…...
MyBatis-Plus的自带分页方法生成的SQL失败:The error occurred while setting parameters
1、error描述 数据库是postgres,Java使用mybatis-plus的分页功能,生成的分页SQL不能正常运行。 "msg": "nested exception is org.apache.ibatis.exceptions.PersistenceException: Error querying database. Cause: com.baomidou.my…...
Redis 的速度为什么这么快
这里的速度快,Redis 的速度快是与 MySQL 等数据库相比较的,与直接操作内存数据相比,Redis 还是略有逊色。 Redis 是一个单线程模型,为什么比其他的多线程程序还要快,原因有以几点: 1、访问的对象不同 Re…...

HarmonyOS实战:自定义时间选择器
前言 最近在日常鸿蒙开发过程中,经常会使用一些时间选择器,鸿蒙官方提供的时间选择器满足不了需求,所以自己动手自定义一些经常会使用到的时间选择器,希望能帮到你,建议点赞收藏! 实现效果 需求分析 默认…...
Flannel后端为UDP模式下,分析数据包的发送方式——tun设备(三)
在分析 Kubernetes 环境中 Flannel UDP 模式的数据包转发时,我们提到 flannel.1 是一个 TUN 设备,它在数据包处理中起到了关键作用。 什么是 TUN 设备? TUN 设备(Tunnel 设备)是 Linux 系统中一种虚拟网络接口&#x…...

6:OpenCV—图像滤波
过滤图像和视频 图像滤波是一种邻域运算,其中输出图像中任何给定像素的值是通过对相应输入像素附近的像素值应用某种算法来确定的。该技术通常用于平滑、锐化和检测图像和视频的边缘。 让我们了解在讨论图像过滤技术、内核和卷积时使用的一些术语的含义。 内核 内…...

pytorch语法学习
启动 python main.py --config llve.yml --path_y test -i output...

5:OpenCV—图像亮度、对比度变换
1.更改图像和视频的亮度 更改亮度 更改图像的亮度是常用的点操作。在此操作中,图像中每个像素的值应增加/减少一个常数。要更改视频的亮度,应对视频中的每一帧执行相同的操作。 如果要增加图像的亮度,则必须为图像中的每个像素添加一些正常…...

Oracle 的V$ACTIVE_SESSION_HISTORY 视图
Oracle 的V$ACTIVE_SESSION_HISTORY 视图 V$ACTIVE_SESSION_HISTORY显示数据库中的 Sampled Session 活动。 它包含每秒拍摄一次的活动数据库会话的快照。如果数据库会话位于 CPU 上或正在等待不属于等待类的事件,则认为该会话处于活动状态。请参阅 view 以了解有…...
redis数据持久化和配置-13(配置 AOF:Appendfsync 策略)
配置 AOF:Appendfsync 策略 在 Redis 中配置仅附加文件 (AOF) 持久性机制涉及选择正确的 appendfsync 策略。此策略指示 Redis 将数据写入磁盘上的 AOF 文件的频率。策略的选择会显著影响数据安全和性能。了解这些策略之间的权衡对于确保 Re…...

【Python 算法零基础 4.排序 ② 冒泡排序】
目录 一、引言 二、算法思想 三、时间复杂度和空间复杂度 1.时间复杂度 2.空间复杂度 四、冒泡排序的优缺点 1.算法的优点 2.算法的缺点 五、实战练习 88. 合并两个有序数组 算法与思路 ① 合并数组 ② 冒泡排序 2148. 元素计数 算法与思路 ① 排序 ② 初始化计数器 ③ 遍历数组…...

Python:操作Excel设置行高和列宽
Python 操作 Excel:轻松设置行高与列宽 📊✨ 在处理 Excel 表格时,除了正确展示数据本身,合理设置行高与列宽也是提升可读性和专业度的关键因素。本文将带你了解如何使用 Python 的 openpyxl 库,优雅地控制 Excel 表格的排版布局,实现行高、列宽的灵活设置与自动适配! …...

docker-volume-backup 备份 ragflow volumes
自定义项目名称 这里我自定义了 ragflow 项目的名称,修改 .env,添加环境配置 # 自定义项目名称 COMPOSE_PROJECT_NAMEragflow创建备份脚本配置文件 在 ragflow/docker 目录下创建文件 docker-compose-backup.yml version: 3services:backup:image: o…...

Axure设计数字乡村可视化大屏:从布局到交互的实战经验分享
乡村治理正从传统模式向“数据驱动”转型。数字乡村可视化大屏作为数据展示的核心载体,不仅能直观呈现乡村发展全貌,还能为决策提供科学依据。本文以Axure为工具,结合实际案例,分享如何从零设计一个功能完备、交互流畅的数字乡村大…...

算法第26天 | 贪心算法、455.分发饼干、376. 摆动序列、 53. 最大子序和
弹性算法理论基础 想清楚 局部最优 是什么,如果可以推导出全局最优,那就是正确的贪心算法 455. 分发饼干 题目 思路与解法 class Solution:def findContentChildren(self, g: List[int], s: List[int]) -> int:res 0i 0j 0g.sort()s.sort()whi…...

PDF处理控件Aspose.PDF教程:以编程方式将 PDF 导出为 JPG
在本节中,我们将探讨如何使用 Aspose.PDF 库将 PDF 文档转换为 JPG 图像。Aspose.PDF 是一个功能强大且用途广泛的库,专为需要以编程方式处理 PDF 文件的开发人员而设计。它提供了丰富的功能,可用于跨多个平台创建、编辑和转换 PDF 文档。其主…...
Vue3+ElementPlus 开箱即用后台管理系统,支持白天黑夜主题切换,通用管理组件,
Vue3ElementPlus后台管理系统,支持白天黑夜主题切换,专为教育管理场景设计。主要功能包括用户管理(管理员、教师、学生)、课件资源管理(课件列表、下载中心)和数据统计(使用情况、教学效率等&am…...

AI大模型应用之评测篇
在看到公司对于AI 工程师 的岗位要求 :“能够熟练使用各种自动化评测工具与方法,对AI 模型的输出进行有效评估” 时,其实比较疑惑,这个是对大模型能力例如像Deepseek ,GPT-4 ,千问,LLAMA这些模型的能力评测,…...

力扣小题, 力扣113.路径总和II力扣.111二叉树的最小深度 力扣.221最大正方形力扣5.最长回文子串更加优秀的算法:中心扩展算法
目录 力扣113.路径总和II 力扣.111二叉树的最小深度 力扣.221最大正方形 力扣5.最长回文子串 更加优秀的算法:中心扩展算法 力扣113.路径总和II 这道题,让我明白回溯了到底啥意思 之前我找的时候,我一直在想,如果可以,请你对比…...

el-form elform 对齐方式调整
如下页面表单,展示后就很丑。 页面表单,有时候我们想着最左侧的应该合理整齐的左对齐,右侧的表单都是右对齐,这样页面看起来会整洁很多。 <el-form class"w-100 a_form" style"padding: 0 15px 0px 15px"…...

JESD204 ip核使用与例程分析(二)
JESD204 ip核使用与例程分析(二) JESD204时钟方案专用差分时钟对例程分析jesd204_0_transport_layer_demapperjesd204_0_sig_chkjesd204_0_clockingjesd204_0 ip核port寄存器AXI-LITE寄存器配置jesd204_phy ip核JESD204时钟方案 图3-1所示为最通用、灵活的时钟解决方案。在图…...
Linux shell 正则表达式高效使用
Linux正则表达式高效使用教程 正则表达式是Linux命令行中强大的文本处理工具,能够极大提高搜索和匹配效率。下面为新手提供一个简单教程,介绍如何在grep和find命令中使用正则表达式。 使用建议:使用grep时要加-E选项使其支持扩展正则表达式&…...

50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | Blurry Loading (毛玻璃加载)
📅 我们继续 50 个小项目挑战!—— Blurry Loading 组件 仓库地址:https://github.com/SunACong/50-vue-projects 项目预览地址:https://50-vue-projects.vercel.app/ ✨ 组件目标 实现一个加载进度条,随着加载进度的…...
C#中的ThreadStart委托
ThreadStart 委托: ThreadStart 是 .NET 中的一个内置委托类型,表示无参数且无返回值的方法。其定义如下: public delegate void ThreadStart(); 通常用于定义线程的入口方法。 List<ThreadStart>: 这是一个泛型集合&…...
GPU加速Kubernetes集群助力音视频转码与AI工作负载扩展
容器编排与GPU计算的结合,为追求性能优化的企业开辟了战略转型的新路径 基于GPU的托管Kubernetes集群不仅是技术选择,更是彻底改变企业处理高负载任务的战略部署方式。 随着人工智能和机器学习项目激增、实时数据处理需求的剧增,以及高性能媒…...
LeetCode[222]完全二叉树的节点个数
思路: 这个节点个数可以使用递归左儿子个数递归右儿子个数1,这个1是根节点,最后结果为节点个数,但我们没有练习到完全二叉树的性质. 完全二叉树的性质是:我简单说一下,大概就是其他节点都满了,就…...
DPDK 技术详解:榨干网络性能的“瑞士军刀”
你是否曾感觉,即使拥有顶级的服务器和万兆网卡,你的网络应用也总是“喂不饱”硬件,性能总差那么一口气?传统的网络处理方式,就像在高速公路上设置了太多的收费站和检查点,限制了数据包的“奔跑”速度。 今…...