【问题标题】:Recursive Compound structure递归复合结构
【发布时间】:2018-11-22 19:47:20
【问题描述】:

我有一个看起来像这样的类:

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&lt;BasicCompound&gt;,则此方法会失败。
  3. 从外部注入mapped_type。那我就不能隐藏ValueWrapper这个东西的使用了。
  4. typdef 上使用继承

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

    这可行,但结构不是严格递归的,因为MyCompound 现在是与BasicCompound 不同的类型。或许类似 CRTP 的方法可以解决这个问题,但是内部复合类型的处理方式必须与其他类型不同。

【问题讨论】:

    标签: c++ recursive-datastructures


    【解决方案1】:

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

    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 提供额外的模板参数。

    【讨论】:

    • 我想这和我的选项(3)在用法上很相似:我不能直接使用内容,但必须通过包装器类型。
    • @user877329:你不能X&lt;X&lt;...&gt;,Y&gt;,其中...使模板参数等效于外部类型。你也不能写X&lt;A,Y&gt;,其中AX&lt;A,Y&gt; 的别名。这是您可以获得的最接近的(实施指南)。
    猜你喜欢
    • 2012-11-10
    • 2012-06-17
    • 1970-01-01
    • 2012-10-22
    • 1970-01-01
    • 1970-01-01
    • 2015-12-29
    • 1970-01-01
    • 2013-11-22
    相关资源
    最近更新 更多