2017-04-11 49 views
0

我正在处理分层实体组件系统。它被称为等级 ,因为实体可能由多个实体组成。如何使用范围创建view_facade -v3

我的层次结构实现为多个链接列表。虽然,我不是依靠几个std::liststd::forward_list。实际上,我有两个向量:1)将实体映射到其第一个孩子; 2)将孩子映射到下一个兄弟姐妹。

我想在这个结构上创建一个ranges::view,但似乎我忘记了一些东西。

我想使用的范围内这样(Complete Code on GitHub):

TEST_CASE("Range adaptors") 
{ 
    auto parentSystem = System<Test::Parent>{}; 
    auto childSystem = System<Test::Child>{}; 
    auto parent0 = parentSystem.add(); 
    auto parent1 = parentSystem.add(); 
    LeftMapped<Test::Parent, System, Test::Child, System> leftMapped(parentSystem, childSystem); 
    leftMapped.addChild(parent0, childSystem.add()); 
    leftMapped.addChild(parent0, childSystem.add()); 
    leftMapped.addChild(parent0, childSystem.add()); 
    leftMapped.addChild(parent1, childSystem.add()); 
    // HERE \/ 
    ranges::for_each(leftMapped.children(parent0), [](Test::Child child) 
    { 
     std::cout << static_cast<Base>(child).id() << std::endl; 
    }); 
} 

,当然还有,使它pipeable与视图和兼容的行动与前进档位的工作(我不这样用概念成语)。

这是我想适应的部分代码:

// A composition should inherit Left Mapped when it is necessary O(1) mapping from parent to children. 
template <typename ParentType, template <typename> class ParentSystemType, typename ChildType, template <typename> class ChildSystemType> 
class LeftMapped 
{ 
public: 
    LeftMapped(ParentSystemType<ParentType>& parent, ChildSystemType<ChildType>& child): 
     m_firstChild(makeProperty<ChildType>(parent)), 
     m_nextSibling(makeProperty<ChildType>(child)) 
    { 

    } 
    ChildType firstChild(ParentType parent) const 
    { 
     return m_firstChild[parent]; 
    } 
    ChildType nextSibling(ChildType child) const 
    { 
     return m_nextSibling[child]; 
    } 
    void firstChild(ParentType parent, ChildType child) 
    { 
     m_firstChild[parent] = child; 
    } 
    void nextSibling(ChildType child, ChildType next) 
    { 
     m_nextSibling[child] = next; 
    } 
    void addChild(ParentType parent, ChildType child) 
    { 
     m_nextSibling[child] = m_firstChild[parent]; 
     m_firstChild[parent] = child; 
    } 

    // HERE \/ I don't know how to properly adapt my container. 
    class ChildrenView : public ranges::view_facade<ChildrenView> { 
     friend ranges::range_access; 
     const LeftMapped& mapped; 
     const ParentType parent; 
     struct cursor 
     { 
      const LeftMapped& mapped; 
      ChildType current; 
      decltype(auto) read() const 
      { 
       return current; 
      } 
      void next() 
      { 
       current = mapped.nextSibling(current); 
      } 
      bool equal(ranges::default_sentinel) const { 
       return current == ChildType{}; 
      } 
     }; 
     cursor begin_cursor() { 
      return {mapped, mapped.firstChild(parent)}; 
     } 
    public: 
     ChildrenView() = default; 
     explicit ChildrenView(const LeftMapped& mapped, ParentType parent) 
      : mapped(mapped), 
      parent(parent) 
     {} 
    }; 

    auto children(ParentType parent) const 
    { 
     return ChildrenView(*this, parent); 
    } 

private: 
    Property<ParentType, ChildType, ParentSystemType> m_firstChild; 
    Property<ChildType, ChildType, ChildSystemType> m_nextSibling; 
}; 

回答

1

,在跳出我的第一件事是,你必须在两者和ChildrenViewChildrenView::cursor参考数据成员。这使得这些类型不可分配,这是range-v3所要求的。尝试将它们更改为指针或std::reference_wrapper s,然后查看是否让你更靠近。

+0

谢谢埃里克。你刚刚得到了问题。虽然我没有足够的时间让std :: reference_wrapper工作,但它仍然在Cursor概念上失败。现在,我只是改变了原始指针的引用。 现在,我希望我的结构能够模拟特定的概念,如ForwardRange。我是否必须创建begin()/ end()方法以及前向迭代器?我认为范围概念应该取代那个迭代器锅炉... – csguth

+1

@csguth'view_facade'为你添加'begin'和'end'。默认'begin'大致返回'basic_iterator begin_cursor())> {this-> begin_cursor()}',默认'end'返回'default_sentinel {}'。如果你想让你的范围为'ForwardRange'建模,那么你的光标需要为'ForwardCursor'建模。值得注意的是,它缺少'basic_iterator'需要实现迭代器相等的'bool equal(const cursor&that)const'。 – Casey