鱼C论坛

 找回密码
 立即注册
查看: 1795|回复: 6

[技术交流] 发一个刷leetcode时突发奇想弄出来的玩意:仿python的variant变量。

[复制链接]
发表于 2020-1-15 16:43:06 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
一直用c++在刷leetcode,但leetcode上的测试数据都是python格式的,调试起来很不方便。
最先是想要弄一个翻译器,把python格式的测试数据翻译成c++ stl能支持的。。。然后越弄越奇怪,就弄出了这么一个玩意儿,算是仿冒python的变量类型把:

源代码发在楼下,先发个说明,算是文档吧- -
  1. #include<vector>
  2. #include "variant.h"  //include头文件

  3. using namespace std;
  4. using namespace croper;  //variant定义在croper命名空间下
  5. int Test1(int, vector<string>);
  6. void Swap(int& a, int& b);


  7. int main() {
  8.         cout << "================================================================================================" << endl;
  9.         cout <<    "1、能接受并输出多种类型的变量,现在支持int,double,bool,string,以及vector 5种类型。"        << endl;
  10.         cout << "================================================================================================" << endl;
  11.         variant a = 5;                      //int
  12.         variant b = 4.99;                   //double
  13.         variant c = "hello world";                        //string
  14.         variant d = false;                  //bool
  15.         variant o;
  16.         cout << a << endl;
  17.         cout << b << endl;
  18.         cout << c << endl;
  19.         cout << d << endl;
  20.         cout << o << endl;
  21.         cout << "================================================================================================" << endl;
  22.         cout << "    2、其中vector特化为python里的list类型,能容纳各种数据类型(其实就是vector<variant>)"          << endl;
  23.         cout << "================================================================================================" << endl;
  24.         variant e = { 5,4.99,false,"hello world" };            //同时容纳多种数据类型
  25.         variant f = { {"there","is","no"},12315,"bigbang" }; //支持嵌套的初始化
  26.         cout << e << endl;
  27.         cout << f << endl;
  28.         f.append(e);                  //可以继续添加元素
  29.         e.append(f);                   //出现环路也可以正确识别
  30.         cout << f << endl;

  31.         cout << "================================================================================================" << endl;
  32.         cout << "       3、可以使用字符串初始化(这其实是最初的目的)                                                                                     " << endl;
  33.         cout << "================================================================================================" << endl;
  34.         variant s1 = Variant_Read("5,Bob,false,[48,22,4.99],[4,5],[125,54]");   //使用字符串初始化
  35.         variant s2 = "5,3,9,[48,22,4.99],[4,5],[125,54]"_V;               //更加简单的写法
  36.         cout << s1 << endl;
  37.         cout << s2 << endl;
  38.        
  39.         cout << "================================================================================================" << endl;
  40.         cout << "       4、可以将自身展开并传递给特定函数:                                                                                                         " << endl;
  41.         cout << "================================================================================================" << endl;
  42.         variant r1 = R"(5,["Allice","Bob","Carol","Dave"])"_V;      
  43.         int x = r1.call(Test1);          //将r1展开传递给test1
  44.         cout << "返回值为" << x << endl;
  45.         cout << endl;

  46.         variant r2 = { 5,2 };
  47.         cout << "调用前r2为" << r2 << endl;
  48.         r2.call(Swap);                   //将r2展开传递给Swap,Swap将交换两个参数的值,这将正确反映到r2上
  49.         cout << "调用后r2为" << r2 << endl;

  50.         cout << "================================================================================================" << endl;
  51.         cout << "       5、大部分运算符重载工作未完工,dict类型尚未完成,敬请期待                                                    " << endl;
  52.         cout << "================================================================================================" << endl;
  53.         system("pause");
  54. }

  55. int Test1(int n, vector<string> v) {
  56.         int ret = 0;
  57.         for (auto s : v) {
  58.                 ret += s.size();
  59.                 for (int i = 0; i < n; ++i) {
  60.                         cout << s << endl;
  61.                 }
  62.                 cout << endl;
  63.         }
  64.         return ret;
  65. }
  66. void Swap(int& a, int& b) {
  67.         int t = a;
  68.         a = b;
  69.         b = t;
  70. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2020-1-15 16:45:46 | 显示全部楼层
.h文件分为4部分

1、variant_meta.h
  1. #ifndef __VARIANT_META_H
  2. #define __VARIANT_META_H
  3. //variant需要用到的某些元编程模块


  4. //检测两个类型是否相同
  5. template<typename T1, typename T2>
  6. class IsSame {
  7. private:
  8.         enum { result = 0};
  9. };
  10. template<typename T>
  11. class IsSame<T,T> {
  12. private:

  13.         enum { result = 1 };
  14. };

  15. //检测两个类型是否能互相转化
  16. template<typename Dest, typename Orig>
  17. class CanMatch{
  18. private:
  19.         static char Test(Dest);
  20.         static int Test(...);
  21.         static Orig MakeOrig();
  22. public:
  23. #pragma warning(disable:4244)
  24.         enum { result = sizeof(Test(MakeOrig())) == sizeof(char) };
  25. #pragma warning(default:4244)
  26. };


  27. //检测某个类型是否是引用
  28. template<typename T>
  29. struct isReference{
  30.         enum { result = 0};
  31. };

  32. template<typename T>
  33. struct isReference<T&> {
  34.         enum { result = 1 };
  35. };

  36. template<typename T>
  37. struct isReference<T&&> {
  38.         enum { result = 1 };
  39. };

  40. #define IF_0(Code)
  41. #define IF_1(Code) Code
  42. #define IF(Bool,Code) IF_##Bool##(Code)

  43. #endif
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-15 16:46:46 | 显示全部楼层
variant_sruct.h
  1. //=======================================================================================
  2. //--------------------------------------------------------------------------------------|
  3. //                          variant类的框架,不含Data部分                                                                |       
  4. //--------------------------------------------------------------------------------------|
  5. //=======================================================================================
  6. #ifndef __VARIANT_STRUCT_H
  7. #define __VARIANT_STRUCT_H

  8. #include <share.h>
  9. #include <iostream>
  10. #include <initializer_list>
  11. #include <string>
  12. #include <vector>
  13. #include <assert.h>
  14. #include "variant_meta.h"

  15. namespace croper {

  16. //================================================================================
  17. //定义开始
  18. //===============================================================================
  19.         class variant {
  20.         private:
  21.                 using string = std::string;
  22.         public:
  23.                 using list = std::vector<variant>;
  24.                 static const variant None;
  25. #ifndef VARIANT_REGISTER_TYPE
  26. #define VARIANT_REGISTER_TYPE
  27. #endif
  28. //****************************************************************************


  29. //==================================================================================
  30. //IData类,定义Data的接口
  31. //==================================================================================
  32.                 struct IData {
  33.                 public:
  34.                         //自身的类型
  35.                         virtual std::string mytype() const = 0;
  36.                         //转化为字符串,对于于__str__方法
  37.                         virtual std::string to_string() const = 0;
  38.                         //返回自身的拷贝
  39.                         virtual IData* copy() const = 0;
  40.                         //以类型T获取数据,会发生类型的默认转化,当类型不匹配时会给出默认值,如果定义了宏VARIANT_STRICT_TYPE_CHECK的话会报错
  41.                         template <typename T> T get_data();
  42.                         //以类型T获取数据,会发生类型的默认转化
  43.                         template <typename T> void trans_type(variant*);
  44.                         //原始数据:类型指定错误会错误
  45.                         template <typename T> T& original_data();


  46.                         //*******************************宏代码块***************************************
  47.                                         //get_data与astype是模板,本身无法继承,这里让get_data调用_get_data_int,_get_data_float等以实现继承
  48. #define VARIANT_REGISTER(T) \
  49.                         virtual T _get_data_##T##() = 0;\
  50.                         virtual void _trans_type_##T##(variant*) = 0;\
  51.                         template<> T get_data<T>(){\
  52.                                 return _get_data_##T##();\
  53.                         }\
  54.                         template<> void trans_type<T>(variant* base) {\
  55.                                 _trans_type_##T##(base);\
  56.                         }
  57.                         VARIANT_REGISTER_TYPE;
  58. #undef VARIANT_REGISTER
  59.                         //****************************************************************************
  60.                 };
  61.                 //声明为友元
  62.                 friend struct IData;
  63.                 //创建Data,解耦合用
  64.                 template <typename T>
  65.                 static std::shared_ptr<IData> CreateData();
  66.                 template <typename T>
  67.                 static std::shared_ptr<IData> CreateData(const T& t);

  68. //========================================================================================
  69. //Judge类,技术类,根据不同的模板参数给出不同的函数                                                                       
  70. //========================================================================================
  71.                 template <int N, typename T, typename my_type, typename templ_arg>
  72.                 struct Judge;
  73.                 //Judge<0>
  74.                 template <typename T, typename my_type, typename templ_arg>
  75.                 struct Judge<0, T, my_type, templ_arg> {
  76.                         static T get_data(my_type*);
  77.                         static void transtype(my_type*, variant*);
  78.                 };
  79.                 //Judge<1>
  80.                 template <typename T, typename my_type, typename templ_arg>
  81.                 struct Judge<1, T, my_type, templ_arg> {
  82.                         static T get_data(my_type* self);
  83.                         static void transtype(my_type*, variant*);
  84.                 };

  85.                 //Judge<2>
  86.                 template <typename T, typename my_type, typename templ_arg>
  87.                 struct Judge<2, T, my_type, templ_arg> {
  88.                         static void transtype(my_type*, variant*);
  89.                 };

  90.                 //Judge<3>
  91.                 template <typename T, typename my_type, typename templ_arg>
  92.                 struct Judge<3, T, my_type, templ_arg> {
  93.                         static void transtype(my_type*, variant*);
  94.                 };

  95.                 //Judge<4>
  96.                 template <typename T, typename my_type, typename templ_arg>
  97.                 struct Judge<4, T, my_type, templ_arg> {
  98.                         static void transtype(my_type*, variant*);
  99.                 };
  100.                 //========================================================================================
  101.                 //DistinguishType类,技术类,当两type相同时返回0,第一个是list时返回1,第二个是list时返回2,能转化时返回3,不能转化时返回4                                                               
  102.                 //========================================================================================
  103.         public:
  104.                 template <typename Dest, typename Orig>
  105.                 struct DistinguishType {
  106.                 public:
  107.                         enum { result = 4 - CanMatch<Dest, Orig>::result };
  108.                 };
  109.                 template <typename T>
  110.                 struct DistinguishType<T, T> {
  111.                         enum { result = 0 };
  112.                 };
  113.                 template <typename T>
  114.                 struct DistinguishType<list, T> {
  115.                         enum { result = 1 };
  116.                 };
  117.                 template <typename T>
  118.                 struct DistinguishType<T, list> {
  119.                         enum { result = 2 };
  120.                 };
  121.                 template <>
  122.                 struct DistinguishType<list, list> {
  123.                         enum { result = 0 };
  124.                 };
  125.                 //========================================================================================
  126.                 //_IData_templ类,技术类
  127.                 //模板分离后的IData,使分离的_get_data_int,_get_data_double等都指向同一个get_data,并使用Judge判断其类型是否匹配,
  128.                 //不匹配时,其将指向一个报错的函数
  129.                 //如果使用if语句会导致虽然这一块永远不会执行但是无法通过编译。
  130.                 //========================================================================================

  131.                 template <typename templ_arg>
  132.                 struct _IData_templ :public IData {
  133.                         virtual templ_arg& get_data() = 0;
  134.                         //*******************************宏代码块***************************************
  135. #define VARIANT_REGISTER(T) \
  136.                         virtual T _get_data_##T##() override{\
  137.                                 return Judge<CanMatch<T,templ_arg>::result,T,_IData_templ,templ_arg>::get_data(this);\
  138.                         }\
  139.                         virtual void _trans_type_##T##(variant* base) override{\
  140.                                 constexpr int d=DistinguishType<T,templ_arg>::result;\
  141.                                 Judge<d, T, _IData_templ, templ_arg>::transtype(this,base);\
  142.                         }
  143.                         VARIANT_REGISTER_TYPE;
  144. #undef VARIANT_REGISTER
  145.                         //****************************************************************************
  146.                 };
  147.                 //=====================================================================
  148.                 //variant类自身的函数
  149.                 //=====================================================================
  150.         private:
  151.                 //使用智能指针指向_data,这样不再需要对_data进行内存管理,且能进行浅拷贝。
  152.                 //python变量也是相似的机制
  153.                 std::shared_ptr<IData> _data;
  154.                 //====================================================================

  155.         public:
  156.                 //构造函数
  157.                 variant();
  158.                 //根据原始数据构造
  159.                 template <typename T> variant(const T& t);
  160.                 //根据多个原始数据构造出列表
  161.                 variant(const std::initializer_list<variant>&);
  162.                 template <typename ...T> variant(const T&... t);
  163.                 //复制构造函数,不需要,直接浅复制即可
  164.                 variant(const variant&) = default;
  165.                 //析构函数,不需要
  166.                 ~variant() = default;

  167.                 //以字符串形式输出Data的类型
  168.                 std::string type() const;
  169.                 //Data是否是某种特定类型
  170.                 template <typename T>bool is_type() const;
  171.                 //将Data转化为某种特定类型,如果不兼容会转化为空值
  172.                 template <typename T>variant& set_type();
  173.                 //将自身重置为None
  174.                 void clear();
  175.                 //转化为字符串:
  176.                 std::string to_string() const;
  177.                 //将自身解包为参数传入function
  178.                 template <typename retT, typename ...TArgs> retT call(retT(*fp)(TArgs...));
  179.                 //将自身解包为参数传入function,返回值为void的重载版本
  180.                 template <typename ...TArgs> void call(void(*fp)(TArgs...));

  181.                 //当自身为list时于尾部插入一个元素。
  182.                 void append(const variant&);
  183.                 //当自身为list时获得list的大小
  184.                 size_t size() const;
  185.                 //当自身为list时返回尾部元素
  186.                 variant& back();

  187.                 //赋值函数
  188.                 template <typename T> variant& operator=(const T&);
  189.                 //赋值函数,std::vector重载版本
  190.                 template <typename T> variant& operator=(const std::vector<T>&);
  191.                 //赋值函数,const char*重载版本,以接受字面常量
  192.                 variant& operator=(const char* sz);
  193.                 //复制构造函数,不需要重写
  194.                 variant& operator=(const variant& v) = default;


  195.                 //转化为特定类型
  196.                 template <typename T> operator T() const;
  197.                 //转化为特定类型,std::vector重载版本
  198.                 template <typename T> operator std::vector<T>() const;
  199.                 //获取原始数据,慎用
  200.                 template <typename T> T& __My_base();
  201.                 template <typename T> const T& __My_base() const;

  202.                 //================================以下是各种运算符的重载==============================

  203.                 //已完成部分
  204.                 //重载<<实现输出
  205.                 friend std::ostream& operator<<(std::ostream& os, const variant&);
  206.                 //重载[]
  207.                 variant& operator[](int i);
  208.                 //const版本
  209.                 const variant& operator[](int i) const;


  210.                 //未完成部分
  211.                 //工作量有点大,有时间慢慢写
  212.                 bool operator==(const variant&);
  213.                 template <typename T> bool operator==(const T&);
  214.                 //template <typename T> bool friend operator== (const T&, const variant&);

  215.                 bool operator!=(const variant&);
  216.                 template <typename T> bool operator!=(const T&);
  217.                 //template <typename T> bool friend operator!=(const T&, const variant&);

  218.                 variant& operator++();
  219.                 variant& operator--();
  220.                 variant operator++(int);
  221.                 variant operator--(int);

  222.                 variant& operator+ (const variant&);
  223.                 template <typename T> variant& operator+(const T&);
  224.                 template <typename T> friend variant& operator+(const T&, const variant&);
  225.                 variant& operator+=(const variant&);
  226.                 template <typename T> variant& operator+= (const T&);

  227.                 variant& operator- (const variant&);
  228.                 template <typename T> variant& operator-(const T&);
  229.                 template <typename T> friend variant& operator-(const T&, const variant&);
  230.                 variant& operator-=(const variant&);
  231.                 template <typename T> variant& operator-=(const T&);

  232.                 variant& operator* (const variant&);
  233.                 template <typename T> variant& operator*(const T&);
  234.                 template <typename T> friend variant& operator*(const T&, const variant&);
  235.                 variant& operator*=(const variant&);
  236.                 template <typename T> variant& operator*=(const T&);

  237.                 variant& operator/ (const variant&);
  238.                 template <typename T> variant& operator/(const T&);
  239.                 template <typename T> friend variant& operator/(const T&, const variant&);
  240.                 variant& operator/=(const variant&);
  241.                 template <typename T> variant& operator/=(const T&);

  242.                 variant& operator% (const variant&);
  243.                 template <typename T> variant& operator%(const T&);
  244.                 template <typename T> friend variant& operator%(const T&, const variant&);
  245.                 variant& operator%=(const variant&);
  246.                 template <typename T> variant& operator%=(const T&);


  247.         };
  248.         //=============================================================================
  249.         //以下是周边函数的声明
  250.         //=============================================================================
  251.         //错误信息,debug模式下输出错误信息,release模式下直接抛出异常
  252.         void ErrorMsg(std::string s);
  253.         //由字符串转化为variant,特色功能
  254.         variant Variant_Read(const std::string&);
  255.         //可以在字符串后加_V以简化实现上述功能
  256.         variant operator ""_V(const char* p, size_t s);


  257.         //=============================================================================
  258.         //声明结束,以下是模板函数的实现代码
  259.         //=============================================================================

  260.         //------------------------------------------------------------------------
  261.         //IData类的函数
  262.         //-------------------------------------------------------------------------
  263.         //原始数据:类型指定错误会错误
  264.         template<typename T>
  265.         inline T & variant::IData::original_data()
  266.         {
  267.                 return dynamic_cast<_IData_templ<T>*>(this)->get_data();
  268.         }
  269.        

  270.         //----------------------------------------------------------------------------
  271.         //Judge类的函数
  272.         //----------------------------------------------------------------------------

  273.         //当原类型与目标类型相同时
  274.         template<typename T, typename my_type, typename templ_arg>
  275.         inline void variant::Judge<0, T, my_type, templ_arg>::transtype(my_type * self, variant * base)
  276.         {
  277.                 //什么也不做
  278.         }

  279.         //当目标类型为list但源类型不为list时,转化为长度为1的list,第一个元素即为自身
  280.         template<typename T, typename my_type, typename templ_arg>
  281.         inline void variant::Judge<1, T, my_type, templ_arg>::transtype(my_type * self, variant * base)
  282.         {
  283.                 base->_data = CreateData<list>(list({ *base }));
  284.         }

  285.         //当目标类型不为list但源类型为list时,将第一个元素转化为目标元素
  286.         template<typename T, typename my_type, typename templ_arg>
  287.         inline void variant::Judge<2, T, my_type, templ_arg>::transtype(my_type * self, variant * base)
  288.         {
  289.                 *base = base[0];
  290.                 base->set_type<T>();
  291.         }

  292.         //当源类型能转化为目标类型时,进行默认转化
  293.         template<typename T, typename my_type, typename templ_arg>
  294.         inline void variant::Judge<3, T, my_type, templ_arg>::transtype(my_type * self, variant * base)
  295.         {
  296.                 base->_data = CreateData<T>(self->get_data());
  297.         }

  298.         //当源类型不能转化为目标类型时,设为默认值
  299.         template<typename T, typename my_type, typename templ_arg>
  300.         inline void variant::Judge<4, T, my_type, templ_arg>::transtype(my_type * self, variant * base)
  301.         {
  302.                 base->_data = CreateData<T>(T());
  303.         }

  304.         template<typename T, typename my_type, typename templ_arg>
  305.         inline T variant::Judge<1, T, my_type, templ_arg>::get_data(my_type * self) {
  306.                 return static_cast<T>(self->get_data());
  307.         }

  308.         template<typename T, typename my_type, typename templ_arg>
  309.         inline T variant::Judge<0, T, my_type, templ_arg>::get_data(my_type * self) {
  310. #ifdef VARIANT_STRICT_TYPE_CHECK
  311.                 std::string s = std::string(typeid(T).name()) + "与" + typeid(templ_arg).name() + "的类型无法匹配";
  312.                 ErrorMsg(s);
  313. #endif
  314.                 return T();
  315.         }

  316.         //------------------------------------------------------------------------------------
  317.         //variant自身的函数
  318.         //----------------------------------------------------------------------------------------

  319.         template<typename T>
  320.         inline variant::variant(const T & t) {
  321.                 operator=(t);
  322.         }


  323.         template<typename T>
  324.         inline bool variant::is_type() const
  325.         {
  326.                 IData *p = &*_data;
  327.                 return dynamic_cast<_IData_templ <T>*>(p) != nullptr;
  328.         }
  329.        
  330.         template<>
  331.         inline bool variant::is_type<void>() const {
  332.                 return !_data;
  333.         }


  334.         template<typename T>
  335.         inline variant & variant::set_type()
  336.         {
  337.                 if (!_data) {
  338.                         _data = CreateData<T>();
  339.                 }
  340.                 _data->trans_type<T>(this);
  341.                 return *this;
  342.         }


  343.         template<typename ...TArgs>
  344.         struct SendArgs {
  345.                 template <typename retT, typename T>
  346.                 static retT call(retT(*fp)(TArgs..., T), variant lst_v, int i, TArgs...args) {
  347.                         return fp(args..., lst_v[i]);
  348.                 }

  349.                 template <typename retT, typename T>
  350.                 static retT call(retT(*fp)(TArgs..., T&), variant lst_v, int i, TArgs...args) {
  351.                         return fp(args..., lst_v[i].__My_base<T>());
  352.                 }

  353.                 template <typename retT, typename T, typename ...TArgs2>
  354.                 static retT call(retT(*fp)(TArgs..., T, TArgs2...), variant lst_v, int i, TArgs...args) {
  355.                         return SendArgs<TArgs..., T>::call(fp, lst_v, i + 1, args..., lst_v[i]);
  356.                 }

  357.                 template <typename retT, typename T, typename ...TArgs2>
  358.                 static retT call(retT(*fp)(TArgs..., T&, TArgs2...), variant lst_v, int i, TArgs...args) {
  359.                         return SendArgs<TArgs..., T&>::call(fp, lst_v, i + 1, args..., lst_v[i].__My_base<T>());
  360.                 }

  361.                 template <typename T>
  362.                 static void call(void(*fp)(TArgs..., T), variant lst_v, int i, TArgs...args) {
  363.                         fp(args..., lst_v[i]);
  364.                 }

  365.                 template <typename T>
  366.                 static void call(void(*fp)(TArgs..., T&), variant lst_v, int i, TArgs...args) {
  367.                         fp(args..., lst_v[i].__My_base<T>());
  368.                 }

  369.                 template < typename T, typename ...TArgs2>
  370.                 static void call(void(*fp)(TArgs..., T, TArgs2...), variant lst_v, int i, TArgs...args) {
  371.                         SendArgs<TArgs..., T>::call(fp, lst_v, i + 1, args..., lst_v[i]);
  372.                 }

  373.                 template < typename T, typename ...TArgs2>
  374.                 static void call(void(*fp)(TArgs..., T&, TArgs2...), variant lst_v, int i, TArgs...args) {
  375.                         SendArgs<TArgs..., T&>::call(fp, lst_v, i + 1, args..., lst_v[i].__My_base<T>());
  376.                 }

  377.         };
  378.         template<typename retT, typename ...TArgs>
  379.         inline retT variant::call(retT(*fp)(TArgs...))
  380.         {
  381.                 variant temp = *this;
  382.                 temp.set_type<list>();
  383.                 list l = temp._data->original_data<list>();
  384.                 return SendArgs<>::call(fp, temp, 0);
  385.         }

  386.         template<typename ...TArgs>
  387.         inline void variant::call(void(*fp)(TArgs...))
  388.         {
  389.                 variant temp = *this;
  390.                 temp.set_type<list>();
  391.                 list l = temp._data->original_data<list>();
  392.                 SendArgs<>::call(fp, temp, 0);
  393.         }


  394.         template<typename T>
  395.         variant & variant::operator=(const T & t)
  396.         {
  397.                 _data = CreateData<T>(t);
  398.                 return *this;
  399.         }


  400.         //赋值函数
  401.         //当右值为std::vector时,类型统一为list(std::vector<variant>)
  402.         template<typename T>
  403.         inline variant & variant::operator=(const std::vector<T>& v)
  404.         {
  405.                 _data = CreateData<list>(v);
  406.                 return *this;
  407.         }

  408.         template<typename T>
  409.         inline variant::operator T() const
  410.         {
  411.                 if (_data == nullptr) {
  412.                         return T();
  413.                 }
  414.                 return _data->get_data<T>();
  415.         }

  416.         template<typename T>
  417.         inline T & variant::__My_base()
  418.         {
  419.                 assert(is_type<T>());
  420.                 return _data->original_data<T>();
  421.         }

  422.         template<typename T>
  423.         inline const T & variant::__My_base() const
  424.         {
  425.                 assert(is_type<T>());
  426.                 return _data->original_data<T>();
  427.         }

  428.         template<typename T>
  429.         inline variant::operator std::vector<T>() const
  430.         {
  431.                 if (!is_type<list>()) {
  432.                         ErrorMsg("variant不是list类型,无法转化为std::vector");
  433.                         return std::vector<T>();
  434.                 }
  435.                 std::vector<T> ret;
  436.                 for (int i = 0; i < this->size(); ++i) {
  437.                         ret.push_back(this->operator[](i));
  438.                 }
  439.                 return ret;
  440.         }
  441. };

  442. #endif
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-15 16:47:19 | 显示全部楼层
3.variant_data.h
  1. #ifndef __VARIANT_DATA_H
  2. #define __VARIANT_DATA_H
  3. #include <string>
  4. #include <vector>
  5. #include <unordered_map>
  6. #include <stack>
  7. #include "variant.h"

  8. namespace croper {
  9.         template <typename T>
  10.         class Data :public variant::_IData_templ<T> {
  11.         public:
  12.                 T data;
  13.                 Data() {};
  14.                 Data(const T& t) :data(t) {};
  15.                 T& get_data() override;
  16.                 std::string mytype() const override;
  17.                 Data* copy() const override;
  18.                 std::string to_string() const override;
  19.         };


  20.         template<typename T>
  21.         inline T& Data<T>::get_data() {
  22.                 return data;
  23.         }

  24.         template<typename T>
  25.         inline std::string Data<T>::mytype() const {
  26.                 return typeid(data).name();
  27.         }

  28.         template<>
  29.         inline std::string Data<std::string>::mytype() const {
  30.                 return "string";
  31.         }

  32.         template<>
  33.         inline std::string Data<variant::list>::mytype() const {
  34.                 return "list";
  35.         }

  36.         template<typename T>
  37.         inline Data<T> * Data<T>::copy() const {
  38.                 return new Data(*this);
  39.         }

  40.         template<typename T>
  41.         inline std::string Data<T>::to_string() const {
  42.                 return std::to_string(data);
  43.         }

  44.         template <>
  45.         inline std::string Data<std::string>::to_string() const {
  46.                 return data;
  47.         }

  48.         template <>
  49.         inline std::string Data<bool>::to_string() const {
  50.                 return data ? "(true)" : "(false)";
  51.         }


  52.         //使用图的dps算法来构造当data的type为list时的字符串算法
  53.         //不能使用树的dps算法,可能会有环路。
  54.         template <>
  55.         inline std::string Data<std::vector<variant>>::to_string() const {       
  56.                 using list = variant::list;
  57.                 struct ele {
  58.                         const list* p;
  59.                         int index;
  60.                 };
  61.                 struct map_ele {
  62.                         int state;
  63.                         std::string sz;
  64.                         map_ele() :state(0), sz("") {};
  65.                 };
  66.                 std::unordered_map<const list*,map_ele> checked;
  67.                 std::stack<ele> stk;
  68.                 const list* p = &data;
  69.                 stk.push({ p,0 });
  70.                 checked[p].sz = "[";
  71.                 while (!stk.empty()) {
  72.                         checked[p].state = 1;
  73.                         int &i = stk.top().index;
  74.                         do {
  75.                                 std::string& sz = checked[p].sz;
  76.                                 const variant& v = (*p)[i];
  77.                                 if (!v.is_type<list>()) {
  78.                                         sz += v.to_string();
  79.                                         sz += ",";
  80.                                 }
  81.                                 else {
  82.                                         map_ele& e = checked[&v.__My_base<list>()];
  83.                                         if (e.state == 2) {
  84.                                                 sz += e.sz;
  85.                                                 sz += ',';
  86.                                         }
  87.                                         else if (e.state == 1) {
  88.                                                 sz += "[...]";
  89.                                                 sz += ',';
  90.                                         }
  91.                                         else
  92.                                         {
  93.                                                 p = &v.__My_base<list>();
  94.                                                 stk.push({ p,0 });
  95.                                                 checked[p].sz = "[";
  96.                                                 break;
  97.                                         }
  98.                                 }
  99.                         } while (++i < p->size());
  100.        

  101.                         while (stk.top().index == p->size()) {
  102.                                 if (p->empty()) {
  103.                                         checked[p].sz.push_back(']');
  104.                                 }
  105.                                 else {
  106.                                         checked[p].sz.back() = ']';
  107.                                 }
  108.                                 checked[p].state = 2;
  109.                                 std::string& sz = checked[p].sz;
  110.                                 stk.pop();
  111.                                 if (stk.empty()) break;
  112.                                 p = stk.top().p;
  113.                                 checked[p].sz += sz;
  114.                                 checked[p].sz +=',';
  115.                                 stk.top().index++;
  116.                         }
  117.                 }
  118.        
  119.                 return checked[&data].sz;
  120.         }

  121.         template <typename T>
  122.         inline std::shared_ptr<variant::IData> variant::CreateData() {
  123.                 return std::make_shared<Data<T>>();
  124.         }

  125.         template <typename T>
  126.         inline std::shared_ptr<variant::IData> variant::CreateData(const T& t) {
  127.                 return std::make_shared<Data<T>>(t);
  128.         }
  129. };

  130. #endif
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-15 16:48:16 | 显示全部楼层
4、variant.h 使用时包含这个就好
  1. //=======================================================================================
  2. //--------------------------------------------------------------------------------------|
  3. //variant类                                                                                                                                                                |       
  4. //Created by Croper                                                                            |
  5. //last modified at Jan.15 2020                                                          |
  6. //仿python变量的变体类。                                                                                                                                |
  7. //主要分为两部分 Variant和Data                                                                                                                        |
  8. //variant本身是一个智能指针的包装,作为表层数据,指向Data                                                                |
  9. //Data是一个实际类型的包装,本身是模板,共同拥有一个接口IData                                                        |
  10. //--------------------------------------------------------------------------------------|
  11. //========================================================================================

  12. #ifndef __VARIANT_H
  13. #define __VARIANT_H

  14. #ifndef VARIANT_REGISTER_TYPE
  15. #define VARIANT_REGISTER_TYPE \
  16.         VARIANT_REGISTER(int)\
  17.         VARIANT_REGISTER(double)\
  18.         VARIANT_REGISTER(bool)\
  19.         VARIANT_REGISTER(string)\
  20.         VARIANT_REGISTER(list)
  21. #endif

  22. #include "variant_meta.h"
  23. #include "variant_struct.h"
  24. #include "variant_data.h"

  25. #endif
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-15 16:49:04 | 显示全部楼层
然后还有一个variant.cpp

  1. #include <sstream>
  2. #include <stack>
  3. #include <string>
  4. #include "variant.h"
  5. using namespace std;
  6. namespace croper {
  7.         const variant variant::None = variant();
  8.         using list = variant::list;
  9.         void ErrorMsg(string s)
  10.         {
  11. #ifdef _DEBUG
  12.                 cerr << s << endl;
  13. #else
  14.                 throw "s";
  15. #endif
  16.         }

  17.         ostream & operator<<(ostream & os, const variant &t)
  18.         {
  19.                 if (t._data == nullptr) {
  20.                         os << "(None)";
  21.                         return os;
  22.                 }
  23.                 os << t._data->to_string();
  24.                 return os;
  25.         }

  26.         //========================================================================================
  27.         //以下是variant的函数



  28.         //构造函数
  29.         variant::variant() {};
  30.         variant::variant(const initializer_list<variant>& l)
  31.         {
  32.                 set_type<list>();
  33.                 for (auto v : l) {
  34.                         append(v);
  35.                 }
  36.         }
  37.         variant Variant_Read_Simple(string& sz, int digit_type) {
  38.                 variant v0;
  39.                 if (sz.empty()) {
  40.                         return v0;
  41.                 }
  42.                 else if (digit_type == 0) {
  43.                         stringstream ss(sz);
  44.                         int i;
  45.                         ss >> i;
  46.                         v0 = i;
  47.                 }
  48.                 else if (digit_type == 1) {
  49.                         stringstream ss(sz);
  50.                         double d;
  51.                         ss >> d;
  52.                         v0 = d;
  53.                 }
  54.                 else if (digit_type == 2) {
  55.                         if (sz == "true" || sz == "True") {
  56.                                 v0 = true;
  57.                         }
  58.                         else if (sz == "false" || sz == "False") {
  59.                                 v0 = false;
  60.                         }
  61.                         else {
  62.                                 if (sz.size() >= 2 && sz[0] == sz.back() && (sz[0] == '\'' || sz[0] == '"')) {
  63.                                         sz = sz.substr(1, sz.size() - 2);
  64.                                 }
  65.                                 v0 = sz;
  66.                         }
  67.                 }
  68.                 return v0;
  69.         }
  70.         variant Variant_Read(const string& sz)
  71.         {
  72.                 variant ret;
  73.                 stack<variant*> stk;
  74.                 stk.push(&ret);
  75.                 bool Recording = false;                //是否正在记录
  76.                 int digit_type = 0;                        //0为整数,1为浮点数,2为字符串
  77.                 bool transfered = false;        //转义标签,上一个字符串是否为转义符。
  78.                 string temp;

  79.                 ret.set_type<list>();
  80.                 for (const char* p = sz.c_str();; p++) {
  81.                         const char& c = *p;
  82.                         variant& v = *stk.top();
  83.                         if (Recording && c == '\0' || !transfered && c == ',' || Recording && !transfered && (c == '[' || c == ']')) {  //结算当前字符串
  84.                                 variant v0= Variant_Read_Simple(temp,digit_type);
  85.                                 v.append(v0);
  86.                                 Recording = false;
  87.                                 if (*p == ',') {
  88.                                         continue;
  89.                                 }
  90.                         }
  91.                         if (!transfered && *p == '[') {
  92.                                 v.append(variant());
  93.                                 v.back().set_type<list>();
  94.                                 stk.push(&v.back());
  95.                                 continue;
  96.                         }
  97.                         else if (!transfered && *p == ']') {
  98.                                 stk.pop();
  99.                                 if (stk.empty()) {
  100.                                         break;
  101.                                 }
  102.                                 continue;
  103.                         }
  104.                         else if (!transfered && !Recording && (*p == ' ' || *p == '\n' || *p == '\t')) {
  105.                                 continue;
  106.                         }
  107.                         else if (*p == '\0') {
  108.                                 break;
  109.                         }
  110.                         else {
  111.                                 if (!transfered && *p == '//') {
  112.                                         transfered = true;
  113.                                         continue;
  114.                                 }
  115.                                 if (!Recording) {
  116.                                         Recording = true;
  117.                                         digit_type = 0;
  118.                                         temp.clear();
  119.                                 }
  120.                                 while (digit_type < 2) {
  121.                                         if (!isdigit(*p) && *p != '-' && *p != '.') {
  122.                                                 digit_type = 2;
  123.                                                 break;
  124.                                         }
  125.                                         if (*p == '-' && !temp.empty()) {
  126.                                                 digit_type = 2;
  127.                                                 break;
  128.                                         }
  129.                                         if (*p == '.') {
  130.                                                 digit_type += 1;
  131.                                                 break;
  132.                                         }
  133.                                         break;
  134.                                 }
  135.                                 temp.push_back(*p);
  136.                         }
  137.                 }
  138.                 if (ret.size() == 0) {
  139.                         return variant();
  140.                 }
  141.                 else if (ret.size() == 1) {
  142.                         return ret[0];
  143.                 }
  144.                 return ret;
  145.         }

  146.         void variant::clear()
  147.         {
  148.                 _data = nullptr;
  149.         }
  150.         string variant::to_string() const
  151.         {
  152.                 if (_data == nullptr) {
  153.                         return "(None)";
  154.                 }
  155.                 return _data->to_string();
  156.         }
  157.         void variant::append(const variant & v)
  158.         {
  159.                 if (!is_type<list>()) {
  160.                         ErrorMsg("错误:variant的类型不是list,无法使用append方法");
  161.                         return;
  162.                 }
  163.                 _data->original_data<list>().push_back(v);
  164.         }

  165.         size_t variant::size() const
  166.         {
  167.                 if (!is_type<list>()) {
  168.                         ErrorMsg("错误:variant的类型不是list,无法使用size方法");
  169.                         return -1;
  170.                 }
  171.                 return _data->original_data<list>().size();
  172.         }

  173.         variant& variant::back()
  174.         {
  175.                 if (!is_type<list>()) {
  176.                         ErrorMsg("错误:variant的类型不是list,无法使用back方法");
  177.                         return *this;
  178.                 }
  179.                 return _data->original_data<list>().back();
  180.         }

  181.         variant & variant::operator=(const char * sz)
  182.         {
  183.                 _data = CreateData<string>(sz);
  184.                 return *this;
  185.         }


  186.         variant & variant::operator[](int i)
  187.         {
  188.                 if (is_type<list>()) {
  189.                         return _data->original_data<list>()[i];
  190.                 }
  191. #ifdef VARIANT_REGISTER_TYPE
  192.                 ErrorMsg("variant的内部类型不是list");
  193. #endif
  194.                 return *this;
  195.         }

  196.         const variant & variant::operator[](int i) const
  197.         {
  198.                 if (is_type<list>()) {
  199.                         return _data->original_data<list>()[i];
  200.                 }
  201. #ifdef VARIANT_REGISTER_TYPE
  202.                 ErrorMsg("variant的内部类型不是list");
  203. #endif
  204.                 return *this;
  205.         }

  206.         bool variant::operator==(const variant & v2)
  207.         {
  208.                 if (_data == v2._data) return true;
  209.                 return false;
  210.         }

  211.         string variant::type() const
  212.         {
  213.                 if (_data == nullptr) {
  214.                         return "void";
  215.                 }
  216.                 return _data->mytype();
  217.         }

  218.         variant operator ""_V(const char* p, size_t s) {
  219.                 return Variant_Read(p);
  220.         }
  221. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-15 16:52:50 | 显示全部楼层
用途嘛。。最初时拿来刷leetcode的题。。。。
现在看来把运算符完善了能搞一些泛型编程,

有兴趣的也可以吐槽下代码,欢迎发表批评,建议,感叹什么的。。
另附github地址
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-7-12 14:04

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表