如何声明引用自身的typedef?

时间:2016-05-13 21:38:24

标签: c++ templates c++11 variadic-templates generic-programming

我有一个Variant类型,我想在JSON解析器中使用它。 JSON中的类型可以包括对象和数组。这些对象和数组可以包含自己类型的成员:

typedef variant<int,float,bool,std::string> baseType;
typedef std::vector<baseType> arrayType; // problem, can't have arrays of arrays
typedef std::unordered_map<std::string,baseType> objType; // problem, can't have objects or arrays within objects.

如何创建&#34;递归&#34;模板型?

类似的东西:

typedef variant<int,float,bool,std::string,std::vector<type>,std::unordered_map<std::string,type> type;

我意识到提升;我对使用它的答案不感兴趣。我试图弄清楚它是如何使用recursive_wrapper的,但是自由使用预处理器宏对我来说非常困难。

修改

在下面的Yakk的帮助下,我已经走到了这一步:

template<typename... Ts>
class Variant;

template<class T>
struct tag
{
    using type=T;
};

template<class X, class A, class B>
struct subst : tag<X>
{};

template<class X, class A, class B>
using subst_t = typename subst<X,A,B>::type;

template<class A, class B>
struct subst<A,A,B> : tag<B>
{};

template<class X, class A, class B>
struct subst<X&,A,B> : tag<subst_t<X,A,B>&>
{};

template<class X, class A, class B>
struct subst<X&&,A,B> : tag<subst_t<X,A,B>&&>
{};

template<class X, class A, class B>
struct subst<X const,A,B> : tag<subst_t<X,A,B>const>
{};

template<class X, class A, class B>
struct subst<X volatile,A,B> : tag<subst_t<X,A,B>volatile>
{};

template<class X, class A, class B>
struct subst<X const volatile,A,B> : tag<subst_t<X,A,B>const volatile>
{};

template<template<class...> class Z, class... Xs, class A, class B>
struct subst<Z<Xs...>,A,B> : tag<Z<subst_t<Xs,A,B>...>>
{};

template<template<class,size_t> class Z, class X, size_t n, class A, class B>
struct subst<Z<X,n>,A,B> : tag<Z<subst_t<X,A,B>,n>>
{};

template<class R, class...Xs, class A, class B>
struct subst<R(Xs...),A,B> : tag<subst_t<R,A,B>(subst_t<Xs,A,B>...)>
{};

struct RecursiveType {};

template<typename Sig>
struct RecursiveVariant
{
    using VariantType = Variant<subst_t<Sig,RecursiveType,RecursiveVariant>>;

    template<typename V,
        typename std::enable_if<
            !std::is_same<RecursiveVariant,typename std::decay<V>::type>::value
            && std::is_convertible<V,VariantType>::value
        >
    ::type>
    RecursiveVariant(V&& vIn)
    :
        m_variant(vIn)
    {}

    RecursiveVariant(){};


    template<typename T, typename... Args>
    void Set(Args&&... args)
    {
        m_variant.Set<T,Args...>(std::forward<Args>(args)...);
    }

    template<typename T>
    const T& Get() const
    {
        return m_variant.Get<T>();
    }

    template<typename T>
    T& Get()
    {
        return m_variant.Get<T>();
    }

    VariantType m_variant;
};

我所拥有的实际变体类型是https://codereview.stackexchange.com/questions/127372/variant-class-that-i-dont-think-is-missing-anything

我认为上面的RecursiveWrapper已经过时了。据我了解,我应该用它作为实际类型,即

RecursiveWrapper<RecursiveType> Variant

但是,这可能不正确,因为我没有指定Variant中允许的类型。关于我不理解的代码的问题是

  1. 什么是RecursiveType
  2. 如何将可变参数模板类型转发到基础Variant