c++ 模板技巧——类型萃取

news2025/5/24 2:15:40
//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();//手动调用Destory
    delete d1;//由基类的析构函数发起Destory调用
    return 0;
}

相比而言动态分发就是常规的虚函数——继承体系,基于该体系,可以实现各种设计模式。比如一个有趣的例子:c++的二次分发与访问者模式-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2384277.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

初步尝试AI应用开发平台——Dify的本地部署和应用开发

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

卷积神经网络中的局部卷积:原理、对比与应用解析

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

重拾童年,用 CodeBuddy 做自己的快乐创作者

某个炎炎的夏日午后&#xff0c;阳光透过稀疏的树叶洒落在地上&#xff0c;一道道光影斑驳陆离。那时候的我们&#xff0c;还只是三五个小朋友&#xff0c;蹲坐在村头的一棵老槐树下&#xff0c;手里握着并不属于自己的游戏掌机&#xff0c;轮流按动着手柄的按键&#xff0c;在…

HarmonyOS实战:自定义时间选择器

前言 最近在日常鸿蒙开发过程中&#xff0c;经常会使用一些时间选择器&#xff0c;鸿蒙官方提供的时间选择器满足不了需求&#xff0c;所以自己动手自定义一些经常会使用到的时间选择器&#xff0c;希望能帮到你&#xff0c;建议点赞收藏&#xff01; 实现效果 需求分析 默认…

6:OpenCV—图像滤波

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

pytorch语法学习

启动 python main.py --config llve.yml --path_y test -i output

5:OpenCV—图像亮度、对比度变换

1.更改图像和视频的亮度 更改亮度 更改图像的亮度是常用的点操作。在此操作中&#xff0c;图像中每个像素的值应增加/减少一个常数。要更改视频的亮度&#xff0c;应对视频中的每一帧执行相同的操作。 如果要增加图像的亮度&#xff0c;则必须为图像中的每个像素添加一些正常…

Oracle 的V$ACTIVE_SESSION_HISTORY 视图

Oracle 的V$ACTIVE_SESSION_HISTORY 视图 V$ACTIVE_SESSION_HISTORY显示数据库中的 Sampled Session 活动。 它包含每秒拍摄一次的活动数据库会话的快照。如果数据库会话位于 CPU 上或正在等待不属于等待类的事件&#xff0c;则认为该会话处于活动状态。请参阅 view 以了解有…

【Python 算法零基础 4.排序 ② 冒泡排序】

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

Python:操作Excel设置行高和列宽

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

docker-volume-backup 备份 ragflow volumes

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

Axure设计数字乡村可视化大屏:从布局到交互的实战经验分享

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

算法第26天 | 贪心算法、455.分发饼干、376. 摆动序列、 53. 最大子序和

弹性算法理论基础 想清楚 局部最优 是什么&#xff0c;如果可以推导出全局最优&#xff0c;那就是正确的贪心算法 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

在本节中&#xff0c;我们将探讨如何使用 Aspose.PDF 库将 PDF 文档转换为 JPG 图像。Aspose.PDF 是一个功能强大且用途广泛的库&#xff0c;专为需要以编程方式处理 PDF 文件的开发人员而设计。它提供了丰富的功能&#xff0c;可用于跨多个平台创建、编辑和转换 PDF 文档。其主…

AI大模型应用之评测篇

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

力扣小题, 力扣113.路径总和II力扣.111二叉树的最小深度 力扣.221最大正方形力扣5.最长回文子串更加优秀的算法:中心扩展算法

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

el-form elform 对齐方式调整

如下页面表单&#xff0c;展示后就很丑。 页面表单&#xff0c;有时候我们想着最左侧的应该合理整齐的左对齐&#xff0c;右侧的表单都是右对齐&#xff0c;这样页面看起来会整洁很多。 <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所示为最通用、灵活的时钟解决方案。在图…

50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | Blurry Loading (毛玻璃加载)

&#x1f4c5; 我们继续 50 个小项目挑战&#xff01;—— Blurry Loading 组件 仓库地址&#xff1a;https://github.com/SunACong/50-vue-projects 项目预览地址&#xff1a;https://50-vue-projects.vercel.app/ ✨ 组件目标 实现一个加载进度条&#xff0c;随着加载进度的…

演示:【WPF-WinCC3D】 3D工业组态监控平台源代码

一、目的&#xff1a;分享一个应用WPF 3D开发的3D工业组态监控平台源代码 二、功能介绍 WPF-WinCC3D是基于 WPF 3D研发的工业组态软件&#xff0c;提供将近200个预置工业模型&#xff08;机械手臂、科幻零部件、熔炼生产线、机加生产线、管道等&#xff09;&#xff0c;支持组态…