鱼C论坛

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

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

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

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

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

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

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

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


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

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

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

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

int Test1(int n, vector<string> v) {
        int ret = 0;
        for (auto s : v) {
                ret += s.size();
                for (int i = 0; i < n; ++i) {
                        cout << s << endl;
                }
                cout << endl;
        }
        return ret;
}
void Swap(int& a, int& b) {
        int t = a;
        a = b;
        b = t;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

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


//检测两个类型是否相同
template<typename T1, typename T2>
class IsSame {
private:
        enum { result = 0};
};
template<typename T>
class IsSame<T,T> {
private:

        enum { result = 1 };
};

//检测两个类型是否能互相转化
template<typename Dest, typename Orig>
class CanMatch{
private:
        static char Test(Dest);
        static int Test(...);
        static Orig MakeOrig();
public:
#pragma warning(disable:4244)
        enum { result = sizeof(Test(MakeOrig())) == sizeof(char) };
#pragma warning(default:4244)
};


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

template<typename T>
struct isReference<T&> {
        enum { result = 1 };
};

template<typename T>
struct isReference<T&&> {
        enum { result = 1 };
};

#define IF_0(Code)
#define IF_1(Code) Code
#define IF(Bool,Code) IF_##Bool##(Code)

#endif
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

#include <share.h>
#include <iostream>
#include <initializer_list>
#include <string>
#include <vector>
#include <assert.h>
#include "variant_meta.h"

namespace croper {

//================================================================================
//定义开始
//===============================================================================
        class variant {
        private:
                using string = std::string;
        public:
                using list = std::vector<variant>;
                static const variant None;
#ifndef VARIANT_REGISTER_TYPE
#define VARIANT_REGISTER_TYPE
#endif
//****************************************************************************


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


                        //*******************************宏代码块***************************************
                                        //get_data与astype是模板,本身无法继承,这里让get_data调用_get_data_int,_get_data_float等以实现继承
#define VARIANT_REGISTER(T) \
                        virtual T _get_data_##T##() = 0;\
                        virtual void _trans_type_##T##(variant*) = 0;\
                        template<> T get_data<T>(){\
                                return _get_data_##T##();\
                        }\
                        template<> void trans_type<T>(variant* base) {\
                                _trans_type_##T##(base);\
                        }
                        VARIANT_REGISTER_TYPE;
#undef VARIANT_REGISTER
                        //****************************************************************************
                };
                //声明为友元
                friend struct IData;
                //创建Data,解耦合用
                template <typename T>
                static std::shared_ptr<IData> CreateData();
                template <typename T>
                static std::shared_ptr<IData> CreateData(const T& t);

//========================================================================================
//Judge类,技术类,根据不同的模板参数给出不同的函数                                                                        
//========================================================================================
                template <int N, typename T, typename my_type, typename templ_arg>
                struct Judge;
                //Judge<0>
                template <typename T, typename my_type, typename templ_arg>
                struct Judge<0, T, my_type, templ_arg> {
                        static T get_data(my_type*);
                        static void transtype(my_type*, variant*);
                };
                //Judge<1>
                template <typename T, typename my_type, typename templ_arg>
                struct Judge<1, T, my_type, templ_arg> {
                        static T get_data(my_type* self);
                        static void transtype(my_type*, variant*);
                };

                //Judge<2>
                template <typename T, typename my_type, typename templ_arg>
                struct Judge<2, T, my_type, templ_arg> {
                        static void transtype(my_type*, variant*);
                };

                //Judge<3>
                template <typename T, typename my_type, typename templ_arg>
                struct Judge<3, T, my_type, templ_arg> {
                        static void transtype(my_type*, variant*);
                };

                //Judge<4>
                template <typename T, typename my_type, typename templ_arg>
                struct Judge<4, T, my_type, templ_arg> {
                        static void transtype(my_type*, variant*);
                };
                //========================================================================================
                //DistinguishType类,技术类,当两type相同时返回0,第一个是list时返回1,第二个是list时返回2,能转化时返回3,不能转化时返回4                                                                
                //========================================================================================
        public:
                template <typename Dest, typename Orig>
                struct DistinguishType {
                public:
                        enum { result = 4 - CanMatch<Dest, Orig>::result };
                };
                template <typename T>
                struct DistinguishType<T, T> {
                        enum { result = 0 };
                };
                template <typename T>
                struct DistinguishType<list, T> {
                        enum { result = 1 };
                };
                template <typename T>
                struct DistinguishType<T, list> {
                        enum { result = 2 };
                };
                template <>
                struct DistinguishType<list, list> {
                        enum { result = 0 };
                };
                //========================================================================================
                //_IData_templ类,技术类
                //模板分离后的IData,使分离的_get_data_int,_get_data_double等都指向同一个get_data,并使用Judge判断其类型是否匹配,
                //不匹配时,其将指向一个报错的函数
                //如果使用if语句会导致虽然这一块永远不会执行但是无法通过编译。
                //========================================================================================

                template <typename templ_arg>
                struct _IData_templ :public IData {
                        virtual templ_arg& get_data() = 0;
                        //*******************************宏代码块***************************************
#define VARIANT_REGISTER(T) \
                        virtual T _get_data_##T##() override{\
                                return Judge<CanMatch<T,templ_arg>::result,T,_IData_templ,templ_arg>::get_data(this);\
                        }\
                        virtual void _trans_type_##T##(variant* base) override{\
                                constexpr int d=DistinguishType<T,templ_arg>::result;\
                                Judge<d, T, _IData_templ, templ_arg>::transtype(this,base);\
                        }
                        VARIANT_REGISTER_TYPE;
#undef VARIANT_REGISTER
                        //****************************************************************************
                };
                //=====================================================================
                //variant类自身的函数
                //=====================================================================
        private:
                //使用智能指针指向_data,这样不再需要对_data进行内存管理,且能进行浅拷贝。
                //python变量也是相似的机制
                std::shared_ptr<IData> _data;
                //====================================================================

        public:
                //构造函数
                variant();
                //根据原始数据构造
                template <typename T> variant(const T& t);
                //根据多个原始数据构造出列表
                variant(const std::initializer_list<variant>&);
                template <typename ...T> variant(const T&... t);
                //复制构造函数,不需要,直接浅复制即可
                variant(const variant&) = default;
                //析构函数,不需要
                ~variant() = default;

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

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

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


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

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

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


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

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

                variant& operator++();
                variant& operator--();
                variant operator++(int);
                variant operator--(int);

                variant& operator+ (const variant&);
                template <typename T> variant& operator+(const T&);
                template <typename T> friend variant& operator+(const T&, const variant&);
                variant& operator+=(const variant&);
                template <typename T> variant& operator+= (const T&);

                variant& operator- (const variant&);
                template <typename T> variant& operator-(const T&);
                template <typename T> friend variant& operator-(const T&, const variant&);
                variant& operator-=(const variant&);
                template <typename T> variant& operator-=(const T&);

                variant& operator* (const variant&);
                template <typename T> variant& operator*(const T&);
                template <typename T> friend variant& operator*(const T&, const variant&);
                variant& operator*=(const variant&);
                template <typename T> variant& operator*=(const T&);

                variant& operator/ (const variant&);
                template <typename T> variant& operator/(const T&);
                template <typename T> friend variant& operator/(const T&, const variant&);
                variant& operator/=(const variant&);
                template <typename T> variant& operator/=(const T&);

                variant& operator% (const variant&);
                template <typename T> variant& operator%(const T&);
                template <typename T> friend variant& operator%(const T&, const variant&);
                variant& operator%=(const variant&);
                template <typename T> variant& operator%=(const T&);


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


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

        //------------------------------------------------------------------------
        //IData类的函数
        //-------------------------------------------------------------------------
        //原始数据:类型指定错误会错误
        template<typename T>
        inline T & variant::IData::original_data()
        {
                return dynamic_cast<_IData_templ<T>*>(this)->get_data();
        }
        

        //----------------------------------------------------------------------------
        //Judge类的函数
        //----------------------------------------------------------------------------

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

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

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

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

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

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

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

        //------------------------------------------------------------------------------------
        //variant自身的函数
        //----------------------------------------------------------------------------------------

        template<typename T>
        inline variant::variant(const T & t) {
                operator=(t);
        }


        template<typename T>
        inline bool variant::is_type() const
        {
                IData *p = &*_data;
                return dynamic_cast<_IData_templ <T>*>(p) != nullptr;
        }
        
        template<>
        inline bool variant::is_type<void>() const {
                return !_data;
        }


        template<typename T>
        inline variant & variant::set_type()
        {
                if (!_data) {
                        _data = CreateData<T>();
                }
                _data->trans_type<T>(this);
                return *this;
        }


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

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

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

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

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

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

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

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

        };
        template<typename retT, typename ...TArgs>
        inline retT variant::call(retT(*fp)(TArgs...))
        {
                variant temp = *this;
                temp.set_type<list>();
                list l = temp._data->original_data<list>();
                return SendArgs<>::call(fp, temp, 0);
        }

        template<typename ...TArgs>
        inline void variant::call(void(*fp)(TArgs...))
        {
                variant temp = *this;
                temp.set_type<list>();
                list l = temp._data->original_data<list>();
                SendArgs<>::call(fp, temp, 0);
        }


        template<typename T>
        variant & variant::operator=(const T & t)
        {
                _data = CreateData<T>(t);
                return *this;
        }


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

        template<typename T>
        inline variant::operator T() const
        {
                if (_data == nullptr) {
                        return T();
                }
                return _data->get_data<T>();
        }

        template<typename T>
        inline T & variant::__My_base()
        {
                assert(is_type<T>());
                return _data->original_data<T>();
        }

        template<typename T>
        inline const T & variant::__My_base() const
        {
                assert(is_type<T>());
                return _data->original_data<T>();
        }

        template<typename T>
        inline variant::operator std::vector<T>() const
        {
                if (!is_type<list>()) {
                        ErrorMsg("variant不是list类型,无法转化为std::vector");
                        return std::vector<T>();
                }
                std::vector<T> ret;
                for (int i = 0; i < this->size(); ++i) {
                        ret.push_back(this->operator[](i));
                }
                return ret;
        }
};

#endif
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

namespace croper {
        template <typename T>
        class Data :public variant::_IData_templ<T> {
        public:
                T data;
                Data() {};
                Data(const T& t) :data(t) {};
                T& get_data() override;
                std::string mytype() const override;
                Data* copy() const override;
                std::string to_string() const override;
        };


        template<typename T>
        inline T& Data<T>::get_data() {
                return data;
        }

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

        template<>
        inline std::string Data<std::string>::mytype() const {
                return "string";
        }

        template<>
        inline std::string Data<variant::list>::mytype() const {
                return "list";
        }

        template<typename T>
        inline Data<T> * Data<T>::copy() const {
                return new Data(*this);
        }

        template<typename T>
        inline std::string Data<T>::to_string() const {
                return std::to_string(data);
        }

        template <>
        inline std::string Data<std::string>::to_string() const {
                return data;
        }

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


        //使用图的dps算法来构造当data的type为list时的字符串算法
        //不能使用树的dps算法,可能会有环路。
        template <>
        inline std::string Data<std::vector<variant>>::to_string() const {        
                using list = variant::list;
                struct ele {
                        const list* p;
                        int index;
                };
                struct map_ele {
                        int state;
                        std::string sz;
                        map_ele() :state(0), sz("") {};
                };
                std::unordered_map<const list*,map_ele> checked;
                std::stack<ele> stk;
                const list* p = &data;
                stk.push({ p,0 });
                checked[p].sz = "[";
                while (!stk.empty()) {
                        checked[p].state = 1;
                        int &i = stk.top().index;
                        do {
                                std::string& sz = checked[p].sz;
                                const variant& v = (*p)[i];
                                if (!v.is_type<list>()) {
                                        sz += v.to_string();
                                        sz += ",";
                                }
                                else {
                                        map_ele& e = checked[&v.__My_base<list>()];
                                        if (e.state == 2) {
                                                sz += e.sz;
                                                sz += ',';
                                        }
                                        else if (e.state == 1) {
                                                sz += "[...]";
                                                sz += ',';
                                        }
                                        else
                                        {
                                                p = &v.__My_base<list>();
                                                stk.push({ p,0 });
                                                checked[p].sz = "[";
                                                break;
                                        }
                                }
                        } while (++i < p->size());
        

                        while (stk.top().index == p->size()) {
                                if (p->empty()) {
                                        checked[p].sz.push_back(']');
                                }
                                else {
                                        checked[p].sz.back() = ']';
                                }
                                checked[p].state = 2;
                                std::string& sz = checked[p].sz;
                                stk.pop();
                                if (stk.empty()) break;
                                p = stk.top().p;
                                checked[p].sz += sz;
                                checked[p].sz +=',';
                                stk.top().index++;
                        }
                }
        
                return checked[&data].sz;
        }

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

        template <typename T>
        inline std::shared_ptr<variant::IData> variant::CreateData(const T& t) {
                return std::make_shared<Data<T>>(t);
        }
};

#endif
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

#ifndef __VARIANT_H
#define __VARIANT_H

#ifndef VARIANT_REGISTER_TYPE
#define VARIANT_REGISTER_TYPE \
        VARIANT_REGISTER(int)\
        VARIANT_REGISTER(double)\
        VARIANT_REGISTER(bool)\
        VARIANT_REGISTER(string)\
        VARIANT_REGISTER(list)
#endif

#include "variant_meta.h"
#include "variant_struct.h"
#include "variant_data.h"

#endif
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-15 16:49:04 | 显示全部楼层
然后还有一个variant.cpp
#include <sstream>
#include <stack>
#include <string>
#include "variant.h"
using namespace std;
namespace croper {
        const variant variant::None = variant();
        using list = variant::list;
        void ErrorMsg(string s)
        {
#ifdef _DEBUG
                cerr << s << endl;
#else
                throw "s";
#endif
        }

        ostream & operator<<(ostream & os, const variant &t)
        {
                if (t._data == nullptr) {
                        os << "(None)";
                        return os;
                }
                os << t._data->to_string();
                return os;
        }

        //========================================================================================
        //以下是variant的函数



        //构造函数
        variant::variant() {};
        variant::variant(const initializer_list<variant>& l)
        {
                set_type<list>();
                for (auto v : l) {
                        append(v);
                }
        }
        variant Variant_Read_Simple(string& sz, int digit_type) {
                variant v0;
                if (sz.empty()) {
                        return v0;
                }
                else if (digit_type == 0) {
                        stringstream ss(sz);
                        int i;
                        ss >> i;
                        v0 = i;
                }
                else if (digit_type == 1) {
                        stringstream ss(sz);
                        double d;
                        ss >> d;
                        v0 = d;
                }
                else if (digit_type == 2) {
                        if (sz == "true" || sz == "True") {
                                v0 = true;
                        }
                        else if (sz == "false" || sz == "False") {
                                v0 = false;
                        }
                        else {
                                if (sz.size() >= 2 && sz[0] == sz.back() && (sz[0] == '\'' || sz[0] == '"')) {
                                        sz = sz.substr(1, sz.size() - 2);
                                }
                                v0 = sz;
                        }
                }
                return v0;
        }
        variant Variant_Read(const string& sz)
        {
                variant ret;
                stack<variant*> stk;
                stk.push(&ret);
                bool Recording = false;                //是否正在记录
                int digit_type = 0;                        //0为整数,1为浮点数,2为字符串
                bool transfered = false;        //转义标签,上一个字符串是否为转义符。
                string temp;

                ret.set_type<list>();
                for (const char* p = sz.c_str();; p++) {
                        const char& c = *p;
                        variant& v = *stk.top();
                        if (Recording && c == '\0' || !transfered && c == ',' || Recording && !transfered && (c == '[' || c == ']')) {  //结算当前字符串
                                variant v0= Variant_Read_Simple(temp,digit_type);
                                v.append(v0);
                                Recording = false;
                                if (*p == ',') {
                                        continue;
                                }
                        }
                        if (!transfered && *p == '[') {
                                v.append(variant());
                                v.back().set_type<list>();
                                stk.push(&v.back());
                                continue;
                        }
                        else if (!transfered && *p == ']') {
                                stk.pop();
                                if (stk.empty()) {
                                        break;
                                }
                                continue;
                        }
                        else if (!transfered && !Recording && (*p == ' ' || *p == '\n' || *p == '\t')) {
                                continue;
                        }
                        else if (*p == '\0') {
                                break;
                        }
                        else {
                                if (!transfered && *p == '//') {
                                        transfered = true;
                                        continue;
                                }
                                if (!Recording) {
                                        Recording = true;
                                        digit_type = 0;
                                        temp.clear();
                                }
                                while (digit_type < 2) {
                                        if (!isdigit(*p) && *p != '-' && *p != '.') {
                                                digit_type = 2;
                                                break;
                                        }
                                        if (*p == '-' && !temp.empty()) {
                                                digit_type = 2;
                                                break;
                                        }
                                        if (*p == '.') {
                                                digit_type += 1;
                                                break;
                                        }
                                        break;
                                }
                                temp.push_back(*p);
                        }
                }
                if (ret.size() == 0) {
                        return variant();
                }
                else if (ret.size() == 1) {
                        return ret[0];
                }
                return ret;
        }

        void variant::clear()
        {
                _data = nullptr;
        }
        string variant::to_string() const
        {
                if (_data == nullptr) {
                        return "(None)";
                }
                return _data->to_string();
        }
        void variant::append(const variant & v)
        {
                if (!is_type<list>()) {
                        ErrorMsg("错误:variant的类型不是list,无法使用append方法");
                        return;
                }
                _data->original_data<list>().push_back(v);
        }

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

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

        variant & variant::operator=(const char * sz)
        {
                _data = CreateData<string>(sz);
                return *this;
        }


        variant & variant::operator[](int i)
        {
                if (is_type<list>()) {
                        return _data->original_data<list>()[i];
                }
#ifdef VARIANT_REGISTER_TYPE
                ErrorMsg("variant的内部类型不是list");
#endif
                return *this;
        }

        const variant & variant::operator[](int i) const
        {
                if (is_type<list>()) {
                        return _data->original_data<list>()[i];
                }
#ifdef VARIANT_REGISTER_TYPE
                ErrorMsg("variant的内部类型不是list");
#endif
                return *this;
        }

        bool variant::operator==(const variant & v2)
        {
                if (_data == v2._data) return true;
                return false;
        }

        string variant::type() const
        {
                if (_data == nullptr) {
                        return "void";
                }
                return _data->mytype();
        }

        variant operator ""_V(const char* p, size_t s) {
                return Variant_Read(p);
        }
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

有兴趣的也可以吐槽下代码,欢迎发表批评,建议,感叹什么的。。
另附github地址
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-1-16 08:22

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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