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

devtools/2024/11/24 14:11:07/

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

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

        构造函数

        拷贝构造函数

        虚拟函数

        纯虚拟函数

        析构函数

类的继承

运算符重写

模板类

        模板参数

数组

        数组的传递

指针与动态内存分配

        

Python:

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-23template<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手机					: 13828778863Email				:  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/136005240class 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-23virtual 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];elsereturn _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-23template<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容器中,可以查找,比较。


http://www.ppmy.cn/devtools/136567.html

相关文章

躺平成长-腾讯云数据库(又消失了一次)

开源竞争&#xff1a; 当你无法彻底掌握技术的时候&#xff0c;你就开源这个技术&#xff0c;形成更多的技术依赖&#xff0c;你会说 这不就是在砸罐子吗&#xff1f;一个行业里面总会有人砸罐子的&#xff0c;你不如先砸罐子&#xff0c;还能听个响声。 数据库的里面清洁的数据…

代码随想录算法训练营day 45|动态规划08

买卖股票的最佳时机1 之前贪心算法有提到过&#xff0c;我们算正区间的总和&#xff0c;只要是正区间就加入总和 dp[i][0]表示第i天持有该股票的最大收益&#xff0c;dp[i][1]表示第i天不持有该股票的最大收益 class Solution { public:int maxProfit(vector<int>&…

uniapp接入BMapGL百度地图

下面代码兼容安卓APP和H5 百度地图官网&#xff1a;控制台 | 百度地图开放平台 应用类别选择《浏览器端》 /utils/map.js 需要设置你自己的key export function myBMapGL1() {return new Promise(function(resolve, reject) {if (typeof window.initMyBMapGL1 function) {r…

【STL】12.unordered_set与unordered_map的模拟实现

一、源码及框架分析 SGI-STL30版本源代码中没有unordered_map和unordered_set&#xff0c;SGI-STL30版本是C11之前的STL版本&#xff0c;这两个容器是C11之后才更新的。但是SGI-STL30实现了哈希表&#xff0c;只容器的名字是hash_map和hash_set&#xff0c;他是作为非标准的容…

【数据结构OJ】【图论】货币套汇(图路径)

题目描述 套汇是指利用货币汇兑率的差异将一个单位的某种货币转换为大于一个单位的同种货币。例如&#xff0c;假定1 美元可以买0.7 英镑&#xff0c;1 英镑可以买9.5 法郎&#xff0c;1法郎可以买到0.16美元。通过货币兑换&#xff0c;一个商人可以从1 美元开始买入&#xff0…

Python 编程开发(01):Bash 命令行基本操作

Bash 是一种功能强大的 shell 语言&#xff08;或命令行语言&#xff09;&#xff0c;广泛用于 Unix 和 Unix-like 操作系统&#xff0c;如 Linux 和 macOS。它提供了一个交互式界面&#xff0c;允许用户输入命令以执行各种操作&#xff0c;如文件管理、程序执行、网络配置等。…

用邻接矩阵实现图的深度优先遍历

问题描述 给定一个无向图&#xff0c;用邻接矩阵作为图的存储结构&#xff0c;输出指定顶点出发的深度优先遍历序列。在深度优先遍历的过程中&#xff0c;如果同时出现多个待访问的顶点&#xff0c;则优先选择编号最小的一个进行访问。 输入描述 第一行输入三个正整数&#…

汽车免拆诊断案例 | 2012款路虎揽胜运动版柴油车加速无力

故障现象  一辆2012款路虎揽胜运动版车&#xff0c;搭载3.0T柴油发动机&#xff08;型号为306DT&#xff09;&#xff0c;累计行驶里程约为10.2万km。车主进厂反映&#xff0c;车辆行驶中加速无力&#xff0c;且发动机故障灯异常点亮。 故障诊断 接车后试车&#xff0c;发动…