c++11实现variant
2022-02-24 本文已影响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