0

Ich habe einen Variant-Typ, den ich in etwas wie einem JSON-Parser verwenden möchte. Ein Typ in JSON kann Objekte und Arrays enthalten. Diese Objekte und Arrays können Mitglieder ihrer eigenen Art enthalten:Wie deklariere ich einen Typedef, der sich selbst referenziert?

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. 

Wie kann ich eine „rekursive“ Templat-Typ erstellen?

Etwas wie:

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

ich bewusst bin Auftrieb; Ich bin nicht an Antworten interessiert, die es verwenden. Ich habe versucht, herauszufinden, wie es mit recursive_wrapper funktioniert, aber die liberale Verwendung von Pre-Prozessor-Makros macht es sehr schwer für mich.

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

Der Typ I ist hier https://codereview.stackexchange.com/questions/127372/variant-class-that-i-dont-think-is-missing-anything

Ich denke, die oben RecursiveWrapper haben tatsächliche Variante:

EDIT

Mit Hilfe von Yakk unten, habe ich so weit gekommen ist weg. Wie ich es verstehe, soll ich es als die tatsächliche Art verwenden, das heißt

RecursiveWrapper<RecursiveType> Variant 

Dies kann jedoch nicht richtig sein, weil nirgendwo habe ich die Typen in Variant erlaubt angegeben. Fragen über den Code, den ich nicht verstehe, sind

  1. Was ist RecursiveType?
  2. Wie kann ich variadische Vorlagentypen an den zugrunde liegenden Variant weiterleiten?
+0

Es scheint, wie Sie Vorlagen mit Containern verwirrend. Ein "Array von Arrays" würde wie folgt aussehen: 'std :: vector >'. Das wäre ein Array von Strings. Könnten Sie näher erläutern, warum "Variante" in Ihrer Frage so gestaltet ist, wie es ist? – Jfevold

+0

Entschuldigung, ich dachte das wäre offensichtlich. "variant" ist templated, weil es als Template-Parameter die Typen akzeptiert, die es halten darf. Damit es einen Container von sich selbst halten kann, muss der typedef in der Lage sein, sich selbst zu referenzieren, damit die Containertypen "vector" und "unordered_map" den gleichen Typ enthalten können. Das ist wahrscheinlich so klar wie Matsch. – NeomerArcana

+0

Ich verstehe immer noch nicht, warum Sie Vorlage so würden. Gibt es eine Situation, in der Sie denselben Code für eine Variante anderer Typen verwenden möchten? – Jfevold

Antwort

Verwandte Themen