接上一主题,C++14中如何设计类似于std::any,使集合在C++中与Python一样支持任意数据?

这篇文章的重点是C++多态的应用,但是如果你是C++新手,

你需要了解以下C++知识:

        构造函数

        拷贝构造函数

        虚拟函数

        纯虚拟函数

        析构函数

类的继承

运算符重写

模板类

        模板参数

数组

        数组的传递

指针与动态内存分配

        

Python:

s = { 3,3,5,9 ,3.14,"神主级","九阳天怒","python"};

print(s)
 

C++:

  

	std::list<int> li = { 1,3,4,5,6,7,8,9 };

	std::vector<_any> li_any = { "焚心妖莲",1,2,15, _t("逆天邪神"),li ,3.14 };

上面一行代码中,有 char Array[], int, wchar_t  Array[]链表Dobule

下面我们设计一个类 _any,它在构造函数如果是这样,上面语句就能编译过关。

class _any {

public:
	template<class T>
	_any(const T& tValue) {

	}
};

int main() {      	  

	std::list<int> li = { 1,3,4,5,6,7,8,9 };

	std::vector<_any> li_any = { "焚心妖莲",1,2,15, _t("逆天邪神"),li ,3.14 };
}

上面最难的地方是在类_any内部中如何保存 tValue的值,如果把类声明为模板类,很容易解决,但是就要在每_any指定模板参数T,这样行不行?

 用: std::shared_ptr吗?

auto s = std::make_shared<T>(tValue);

也不行,变量声明也要带T的参数。

那应该怎么办了,查了一个资料,最后就是用C++的多态

多态是C++中的一个核心概念,它允许基类的指针或引用调用派生类中定义的方法。多态性通过函数重写和函数重载提供。

看下面代码,你明白了吗?

上在代码还存在一个问题?

上面 “焚心妖莲” 传递的是数组 T = char Array[]  和  T = wchar_t Array[],没关系,改一下就行,在_any再加

个构造函数?

    /// <summary>
    /// 传递的是数组
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="n"></typeparam>
    /// <param name="arr"></param>
    /// 创建时间: 2024-11-23      最后一次修改时间:2024-11-23
    template<typename T, std::size_t n>
    _any(T(&arr)[n]) : _pData(new _AnyHelper<std::decay_t<T>>(arr,n))
    {              
        
    }

下面给出完整的代码,这代码也是初步的,还有很多要修改之处:

  _any.h

/******************************************************************
文件名				: _any.h

作者					: 李锋

功能					: std::any

手机					: 13828778863

Email				:  ruizhilf@139.com

创建时间				: 2024年11月23日

最后一次修改时间		:  2024年11月23日



 https://baike.baidu.com/item/deque/849385?fr=ge_ala

******************************************************************/
#pragma once
///
#include "__std_in.h"


using lf::m;

///
__STD_BEGIN_
///
/*
感谢作者:

参考: C++ std::any的模拟实现  https://blog.csdn.net/qq_54121864/article/details/136005240

 class Any
{
private:
	class AnyHelperBase
	{
	public:
		virtual const std::type_info& Type()const = 0;
		virtual AnyHelperBase* Clone()const = 0;
	};
	template<typename T>
	class AnyHelper :public AnyHelperBase
	{
	public:
		T data;
		template<typename ...Args>
		AnyHelper(Args&&... args) :data(std::forward<Args>(args)...) {}
		AnyHelper(const AnyHelper& other) :data(other.data) {}
		AnyHelper(const T& value) :data(value) {}
		virtual const std::type_info& Type()const
		{
			return typeid(T);
		}
		virtual AnyHelper* Clone()const
		{
			return new AnyHelper(*this);
		}
	};
	template<typename T>
	friend T AnyCast(const Any& any);
	template<typename T>
	friend T AnyCast(Any& any);
	template<typename T>
	friend T AnyCast(Any&& any);
	template<typename T>
	friend const T* AnyCast(const Any* any);
	template<typename T>
	friend T* AnyCast(Any* any);
	AnyHelperBase* data;
public:
	Any() :data(nullptr) {}
	template<typename T>
	Any(const T& value) : data(new AnyHelper<std::decay_t<T>>(value)) {}
	Any(const Any& other) :data(other.data->Clone()) {}
	Any(Any&& other) :data(other.data)
	{
		other.data = nullptr;
	}
	const std::type_info& Type()const
	{
		return data->Type();
	}
	bool HasValue()const
	{
		return data != nullptr;
	}
	void Reset()
	{
		if (data != nullptr)
			delete data;
		data = nullptr;
	}
	template<typename T>
	Any& operator=(const T& value)
	{
		if (data != nullptr)
			delete data;
		data = new AnyHelper<std::decay_t<T>>(value);
		return *this;
	}
	Any& operator=(const Any& other)
	{
		if (data != nullptr)
			delete data;
		data = other.data->Clone();
		return *this;
	}
	Any& operator=(Any&& other)
	{
		if (data != nullptr)
			delete data;
		data = other.data;
		other.data = nullptr;
		return *this;
	}
	void Swap(Any& other)
	{
		AnyHelperBase* temp = this->data;
		this->data = other.data;
		other.data = temp;
	}
	template<typename T, typename ...Args>
	std::decay_t<T>& Emplace(Args&&... args)
	{
		if (data != nullptr)
			delete data;
		auto temp = new AnyHelper<std::decay_t<T>>(std::forward<Args>(args)...);
		data = temp;
		return temp->data;
	}
	~Any()
	{
		if (data != nullptr)
			delete data;
	}
};

template<typename T>
T AnyCast(const Any& any)
{
	auto p = dynamic_cast<Any::AnyHelper<std::decay_t<T>>*>(any.data);
	if (p == nullptr)
		throw std::runtime_error("Bad any cast!");
	return p->data;
}
template<typename T>
T AnyCast(Any& any)
{
	auto p = dynamic_cast<Any::AnyHelper<std::decay_t<T>>*>(any.data);
	if (p == nullptr)
		throw std::runtime_error("Bad any cast!");
	return p->data;
}
template<typename T>
T AnyCast(Any&& any)
{
	auto p = dynamic_cast<Any::AnyHelper<std::decay_t<T>>*>(any.data);
	if (p == nullptr)
		throw std::runtime_error("Bad any cast!");
	return p->data;
}
template<typename T>
const T* AnyCast(const Any* any)
{
	auto p = dynamic_cast<Any::AnyHelper<std::decay_t<T>>*>(any->data);
	if (p == nullptr)
		return nullptr;
	return &p->data;
}
template<typename T>
T* AnyCast(Any* any)
{
	auto p = dynamic_cast<Any::AnyHelper<std::decay_t<T>>*>(any->data);
	if (p == nullptr)
		return nullptr;
	return &p->data;
}


*/


///
class _any {
public:
 
	class _AnyHelperBase
	{
	public:
		virtual const std::type_info& Type()const = 0; // { return typeid(nullptr); }
		virtual _AnyHelperBase* Clone() const = 0; //{ return nullptr; }
		virtual bool Equal(const _any& r)const = 0; // { return false; }
		virtual void* GetDataPointer()const = 0; // return null; }
	};

	template<typename T>
	class _AnyHelper :public _AnyHelperBase
	{
	public:
		/// <summary>
		/// 用数组来保存T类型数据,如果是单个T类型数据,数据就是 _data[0],
		/// 否则是 _data.GetDataPointer(),如字符串。
		/// </summary>
		lf::_Array<T> _data;
	public: //-------------------------------构造
		_AnyHelper(const T* pt, const size_t& nCount) {
			_data.SetBuffer(nCount + 1);
			_data.Add(pt, nCount);
			_data.ZeroBufferAll();
		}

		/// <summary>
		/// 拷贝构造
		/// </summary>
		/// <param name="r"></param>
		_AnyHelper(const _AnyHelper& r) {
			_data = r._data;
		}

	public: //-----------------------------------重写
		virtual const std::type_info& Type()const override
		{
			return typeid(T);
		}

		/// <summary>
		/// 返回一个新的对象指针
		/// </summary>
		/// <returns></returns>
		virtual _AnyHelper* Clone()const override
		{
			return new _AnyHelper(*this);
		}



		/// <summary>
		/// 原则:
		///		相同数据才判断是否相等
		/// 
		/// </summary>
		/// <param name="r"></param>
		/// <returns></returns>
		/// 创建时间: 2024-11-23      最后一次修改时间:2024-11-23
		virtual bool Equal(const _any& r)const override{
			if (Type() == r._pData->Type()) { 
				return  _data == ((_AnyHelper<T>*)r._pData)->_data;
			} 
			return false;
		}

		virtual void* GetDataPointer()const override {
			if (_data.size() == 0)
				return nullptr;
			else if (_data.size() == 1)
				return &_data[0];
			else
				return _data.DataPointer();
		}

	public: //-----------------------------------------运算符重载
		 
	};

public: //-------------------------------------------------_any
	_AnyHelperBase* _pData;   
public:
	
	_any() :_pData(nullptr) {};



	/// <summary>
	/// 传递的是数组
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <typeparam name="n"></typeparam>
	/// <param name="arr"></param>
	/// 创建时间: 2024-11-23      最后一次修改时间:2024-11-23
	template<typename T, std::size_t n>
	_any(T(&arr)[n]) : _pData(new _AnyHelper<std::decay_t<T>>(arr,n))
	{              
		
	}


	template<class T>
	_any(const T& tValue) :_pData(new _AnyHelper<std::decay_t<T>>(&tValue,1)) {
 
	}

	_any(const _any& other) : _pData(other._pData->Clone()) {
	
	}

	~_any() {
		if (_pData != 0)
			delete _pData;	 
	}

	//-------------------------------------运算符重载
	bool operator==(const _any& r)const {
				 
		return _pData->Equal(r);
 
	}


	void* GetDataPointer()const {
		return _pData->GetDataPointer();
	}

	template<class T>
	const T& ConvertTo() const {
 
		const T* pt = (T*)_pData->GetDataPointer();

		return *pt;
	}
};


///
  

///
__STD_END_
///

下面是例子:

int main() {      	  
	 
	std::list<int> li = { 1,3,4,5,6,7,8,9 };

	std::vector<_any> li_any = { "焚心妖莲",1,2,15, _t("逆天邪神"),li ,3.14 };

	_any ali = li;

	auto li2 = ali.ConvertTo<std::list<int>>();

	_pn(li2);  


	auto f = std::find(li_any.begin(), li_any.end(), li);

	if (f != li_any.end())
		std::cout << (*f)._pData->Type().name() << "\n";

	 
	f = std::find(li_any.begin(), li_any.end(), 3.14);

	if (f != li_any.end())
		std::cout << (*f)._pData->Type().name() << "\n";

 
    return 0;
	 
}

输出结果:

注意:下一步,如何设计 _any类的运算符的 ==  >  <  ,因为要

把_any中用在集合中,或其他std容器中,可以查找,比较。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AndroidStudio与开发板调试时连接失败或APP闪退的解决方案,涉及SELINUX及获取Root权限

现象 用AndroidStudio打开工程代码,点击运行后,报错: 解决方案 具体原因是尝试运行 su(通常用于获取超级用户权限)时失败了,提示 “Permission denied” 通过 CONFIG_SECURITY_SELINUX 变量控制 SElinux 开启或关闭 在vim /rk3568_android_sdk/device/rockchip/rk…

数据结构 (6)栈的应用举例

1. 递归调用 递归函数在执行时&#xff0c;会将每一层的函数调用信息&#xff08;包括局部变量、参数和返回地址&#xff09;存储在栈中。当递归函数返回时&#xff0c;这些信息会从栈中弹出&#xff0c;以便恢复之前的执行状态。栈的后进先出&#xff08;LIFO&#xff09;特性…

QT 网络编程 数据库模块 TCP UDP QT5.12.3环境 C++实现

一、网络编程 1. 模块引入 QT network 2. 头文件 #include <QTcpServer> //TCP服务端使用 #include <QTcpSocket> //TCP服务器和客户端都使用 3. TCP网络编程流程 1) 服务端 实例化QTcpServer对象----------------------------->socket 进入监听状态…

使用ENSP实现NAT

一、项目拓扑 二、项目实现 1.路由器AR1配置 进入系统试图 sys将路由器命名为R1 sysname R1关闭信息中心 undo info-center enable进入g0/0/0接口 int g0/0/0将g0/0/0接口IP地址配置为12.12.12.1/30 ip address 12.12.12.1 30进入e0/0/1接口 int g0/0/1将g0/0/1接口IP地址配置…

Python的tkinter如何把日志弄进文本框(Text)

当我们用python的Tkinter包给程序设计界面时&#xff0c;在有些时候&#xff0c;我们是希望程序的日志显示在界面上的&#xff0c;因为用户也需要知道程序目前运行到哪一步了&#xff0c;以及程序当前的运行状态是否良好。python的通过print函数打印出来的日志通常显示在后台&a…

flux的版本

1.flux1-dev.safetensors https://huggingface.co/black-forest-labs/FLUX.1-devhttps://huggingface.co/black-forest-labs/FLUX.1-dev原生的23.8G的模型。原生12B的模型,float16的。需要配合ae.safetensors,flux1-dev.safetensors以及clip-l和T5的权重使用,注意ae.sft和f…

阿里云私服地址

1.解压apache-maven-3.6.1-bin 2.配置本地仓库&#xff1a;修改conf/dettings.xml中的<localReoisitory>为一个指定目录。56行 <localRepository>D:\apache-maven-3.6.1-bin\apache-maven-3.6.1\mvn_repo</localRepository> 3.配置阿里云私服&#xff1a;…

【大数据学习 | Spark-Core】yarn-client与yarn-cluster的区别

1. yarn的提交命令 # yarn的提交命令参数 --master yarn #执行集群 --deploy-mode # 部署模式 --class #指定运行的类 --executor-memory #指定executor的内存 --executor-cores # 指定核数 --num-executors # 直接指定executor的数量 --queue # 指定队列 2. yarn-client模式…

【汽车制动】汽车制动相关控制系统

目录 1.ABS (Anti-lock Brake System&#xff0c;防抱死制动系统) 2.EBD&#xff08;Electronic Brake-force Distribution&#xff0c;电子制动力分配系统&#xff09; 3.TCS&#xff08;Traction Control System&#xff0c;牵引力控制系统&#xff09; 4.VDC&#xff08…

《TCP/IP网络编程》学习笔记 | Chapter 15:套接字与标准 I/O

《TCP/IP网络编程》学习笔记 | Chapter 15&#xff1a;套接字与标准 I/O 《TCP/IP网络编程》学习笔记 | Chapter 15&#xff1a;套接字与标准 I/O标准 I/O 函数标准 I/O 函数的两个优点标准 I/O 函数和系统函数之间的性能对比标准 I/O 函数的几个缺点 使用标准 I/O 函数利用 fd…

<OS 有关> ubuntu 24 不同版本介绍 安装 Vmware tools

原因 想用 apt-get download 存到本地 / NAS上&#xff0c;减少网络流浪。 看到 VMware 上的确实有 ubuntu&#xff0c;只是版本是16。 ubuntu 版本比较&#xff1a;LTS vs RR LTS: Long-Term Support 长周期支持&#xff0c; 一般每 2 年更新&#xff0c;会更可靠与更稳定…

支持多种快充协议和支持多种功能的诱骗取电协议芯片

汇铭达XSP15是一款应用于手持电动工具、智能家居、显示器、音箱等充电方案的大功率快充协议芯片&#xff0c;支持最大功率100W给设备快速充电&#xff0c;大大缩短了充电时间。芯片支持通过UART串口发送电压/电流消息供其它芯片读取。支持自动识别连接的是电脑或是充电器。支持…

【一篇搞定配置】网络分析工具WireShark的安装与入门使用

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;各种软件安装与配置_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1.…

JavaWeb之综合案例

前言 这一节讲一个案例 1. 环境搭建 然后就是把这些数据全部用到sql语句中执行 2.查询所有-后台&前台 我们先写后台代码 2.1 后台 2.2 Dao BrandMapper&#xff1a; 注意因为数据库里面的名称是下划线分割的&#xff0c;我们类里面是驼峰的&#xff0c;所以要映射 …

【STM32】MPU6050初始化常用寄存器说明及示例代码

一、MPU6050常用配置寄存器 1、电源管理寄存器1&#xff08; PWR_MGMT_1 &#xff09; 此寄存器允许用户配置电源模式和时钟源。 DEVICE_RESET &#xff1a;用于控制复位的比特位。设置为1时复位 MPU6050&#xff0c;内部寄存器恢复为默认值&#xff0c;复位结束…

隐私友好型分析平台Plausible Analytics

什么是 Plausible Analytics &#xff1f; Plausible Analytics 是一个简单、轻量级&#xff08;小于1KB&#xff09;、开源且隐私友好的网站分析工具&#xff0c;旨在作为 Google Analytics 的替代品。它不使用 cookies 并且完全符合 GDPR、CCPA 和 PECR 法规&#xff0c;因此…

Flutter:RotationTransition旋转动画

配置vsync&#xff0c;需要实现一下with SingleTickerProviderStateMixinclass _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin{// 定义 AnimationController late AnimationController _controller;overridevoid initState() {super…

【大数据学习 | Spark-Core】Spark提交及运行流程

spark的集群运行结构 我们要选择第一种使用方式 命令组成结构 spark-submit [选项] jar包 参数 standalone集群能够使用的选项。 --master MASTER_URL #集群地址 --class class_name #jar包中的类 --executor-memory MEM #executor的内存 --executor-cores NUM # executor的…

青训营刷题笔记16

问题描述 小R从班级中抽取了一些同学&#xff0c;每位同学都会给出一个数字。已知在这些数字中&#xff0c;某个数字的出现次数超过了数字总数的一半。现在需要你帮助小R找到这个数字。 测试样例 样例1&#xff1a; 输入&#xff1a;array [1, 3, 8, 2, 3, 1, 3, 3, 3] 输出…

C4D技巧总结

鼠标右键单击这两个小箭头可以把参数恢复到默认值&#xff01; 对象坐标 全局坐标 按住Alt键&#xff0c;点击挤压&#xff08;或者其他绿色的图标&#xff09;&#xff0c;可以快速形成父子级效果&#xff01;