我有一个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
的类型是正确的。关于我不明白的代码的问题有:
- 什么是
RecursiveType
? - 如何将可变模板类型转发到底层
Variant
?
好像你混淆模板用的容器。一个“数组数组”将看起来像'std :: vector>'。这将是一个字符串数组的数组。你能否详细说明为什么你的问题中的'variant'是模板化的? –
Jfevold
对不起,我认为这很明显。 'variant'是模板化的,因为它需要模板参数,它是允许保存的类型。为了让它保存自己的容器,typedef需要能够引用它自己,以便容器类型'vector'和'unordered_map'能够包含相同的类型。这可能像泥巴一样清晰。 – NeomerArcana
我仍然不明白你为什么要模板。是否有这种情况需要使用相同的代码来处理其他类型的变体? – Jfevold