美文网首页
c++11实现variant

c++11实现variant

作者: 一路向后 | 来源:发表于2022-02-24 22:49 被阅读0次

    1.头文件

    #ifndef _MXCOMP_VARIANT_H_
    #define _MXCOMP_VARIANT_H_
    
    #include <iostream>
    #include <cassert>
    
    namespace mxcomp {
        template<size_t N, typename... Types> struct GetType { };
    
        template<size_t N, typename T, typename... Types>
        struct GetType<N, T, Types...> {
            using type = typename GetType<N-1, Types...>::type;
        };
    
        template<typename T, typename... Types>
        struct GetType<0, T, Types...> {
            using type = T;
        };
    
        template<typename S, size_t N, typename... Types> struct GetIndex { };
    
        template<typename S, size_t N, typename T, typename... Types>
        struct GetIndex<S, N, T, Types...> {
            const static size_t value = GetIndex<S, N+1, Types...>::value;
        };
    
        template<typename T, size_t N, typename... Types>
        struct GetIndex<T, N, T, Types...> {
            const static size_t value = N;
        };
    
        template <size_t S, size_t N, typename... Types>
        struct GetIndex<char[S], N, std::string, Types...> {
            const static size_t value = N;
        };
    
        template<typename... Types> struct Variant_;
    
        template<size_t N, class... Types>
        typename GetType<N, Types...>::type &get(Variant_<Types...> &v) {
            return v.template Get<N>();
        }
    
        template<size_t N, class... Types>
        const typename GetType<N, Types...>::type &get1( const Variant_<Types...> &v) {
            return v.template Get<N>();
        }
    
        template<typename... Types>
        struct Variant_ {
            size_t type = (size_t)-1;
            typedef void (Variant_<Types...>::*DeleteFunction)();
            DeleteFunction del = 0;
            void *data = 0;
    
            template<size_t N>
            void _del()
            {
                if(data != 0)
                {
                    using T = typename GetType<N, Types...>::type;
                    delete (T*)data;
                    data = 0;
                    type = (size_t)-1;
                }
            }
    
            Variant_<Types...>(){}
    
            template<size_t N>
            void init()
            {
                if(data == 0)
                {
                    assert(type  == (size_t)-1);
    
                    using T = typename GetType<N, Types...>::type;
    
                    type = N;
    
                    data = new T();
    
                    del = &Variant_<Types...>::_del<N>;
                }
            }
    
            ~Variant_<Types...>()
            {
                if(data)
                {
                    assert(del);
    
                    (this->*del)();
                }
            }
    
            template<size_t N>
            void Set(const typename GetType<N, Types...>::type &val)
            {
                init<N>();
    
                assert(type == N || type  == (size_t)-1);
    
                type = N;
    
                *((typename GetType<N, Types...>::type *)data) = val;
            }
    
            template<size_t N>
            typename GetType<N, Types...>::type &Get()
            {
                init<N>();
    
                assert(type == N && data);
    
                return *((typename GetType<N, Types...>::type *)data);
            }
    
            template<size_t N>
            const typename GetType<N, Types...>::type &Get() const
            {
                assert(type == N && data);
    
                return *((const typename GetType<N, Types...>::type *)data);
            }
    
            template<typename T>
            Variant_<Types...> &operator=(const T &val)
            {
                Set< GetIndex<T, 0, Types...>::value >(val);
    
                return *this;
            }
    
            template<typename T>
            const T &as() const
            {
                return Get<GetIndex<T, 0, Types...>::value>();
            }
    
            template<typename T>
            T &as()
            {
                return Get<GetIndex<T, 0, Types...>::value>();
            }
    
        protected:
            Variant_<Types...>(const Variant_<Types...> &v) {}
    
        };
    }
    
    #endif
    

    2.cpp文件

    #include <iostream>
    #include "variant.h"
    
    using namespace std;
    
    int main()
    {
        mxcomp::Variant_<int, float, std::string> variant;
    
        int a = 1.1;
        int b = 2;
    
        variant = a;
        variant = b;
    
        //cout << variant.as() << endl;
        //variant.as<int>();
    
        cout << variant.as<int>() << endl;
    
    
        return 0;
    }
    

    3.编译源码

    $ g++ -o variant variant.cpp -std=c++11
    

    4.运行及其结果

    $ ./variant 
    2
    

    相关文章

      网友评论

          本文标题:c++11实现variant

          本文链接:https://www.haomeiwen.com/subject/zqbtrrtx.html