2016-05-13 15 views
0

我有一個Variant類型,我想用於像JSON解析器的東西。 JSON中的類型可以包含對象和數組。這些對象和數組可以包含它們自己類型的成員:如何聲明一個引用自身的typedef?

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. 

如何創建「遞歸」模板類型?

喜歡的東西:

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; 
}; 

實際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
+0

好像你混淆模板用的容器。一個「數組數組」將看起來像'std :: vector >'。這將是一個字符串數組的數組。你能否詳細說明爲什麼你的問題中的'variant'是模板化的? – Jfevold

+0

對不起,我認爲這很明顯。 'variant'是模板化的,因爲它需要模板參數,它是允許保存的類型。爲了讓它保存自己的容器,typedef需要能夠引用它自己,以便容器類型'vector'和'unordered_map'能夠包含相同的類型。這可能像泥巴一樣清晰。 – NeomerArcana

+0

我仍然不明白你爲什麼要模板。是否有這種情況需要使用相同的代碼來處理其他類型的變體? – Jfevold

回答