递归复合结构

时间:2018-11-22 19:47:21

标签: c++ recursive-datastructures

我有一堂课,看起来像这样:

template<class KeyType, class... Types>
class BasicCompound
    {
    public:
        using mapped_type = std::variant
            <
              ValueWrapper<BasicCompound>
            , ValueWrapper<Types>...
            >;

        using key_type = KeyType;

       // Accessors for retreiving and modifying content
       // ...

    private:
        std::map<key_type, mapped_type> m_content;
    };

ValueWrapper决定将内容放入行内或放在std::unique_ptr中。是否可以通过类似的接口(可能通过某种代理)将递归性设置为可选?通过可选,我的意思是用户不应自动获得将BasicCompound存储在其内部的可能性,而应在类型列表中进行指定。

我的想法:

  1. using指令不起作用。不能在其自身中定义新类型,并且不允许预先声明以下typedef。
  2. bool添加到类型列表,并将std::conditional_t用于mapped_type。但是,如果用户要存储X<BasicCompound>,则此方法将失败。
  3. 从外部注入mapped_type。然后,我无法隐藏ValueWrapper东西的使用。
  4. typdef上使用继承,例如

    struct MyCompound : BasicCompound<std::string, MyCompound, int> {};
    

    这可行,但是结构不是严格递归的,因为MyCompound现在是与BasicCompound不同的类型。也许类似CRTP的方法可以解决该问题,但是内部化合物类型必须与其他类型区别对待。

1 个答案:

答案 0 :(得分:0)

您不能将类模板的特殊化用作该特殊化的模板参数之一;没有办法写,它的名字会无限长。但是,您可以使用包装器来保存递归类型:

template<class> class MaybeRecursive;

template<class T>
struct Wrapper {
  using type=T;
};
struct MRWrapper {
  using type=MaybeRecursive<MRWrapper>;
};

template<class T>
struct MaybeRecursive {
  using type=typename T::type;
  type *child;
};

void f() {
  int x;
  MaybeRecursive<Wrapper<int>> nonrec={&x};
  MRWrapper::type rec={&rec};
}
可以将

MRWrapper用作类模板,以为MaybeRecursive提供附加的模板参数。