0

我正在研究分层实体组件系统。之所以称为层次结构,是因为一个实体可能由多个实体组成。

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

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

我想以这种方式使用范围(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;
    });
}

当然,使其可用于处理与前向范围兼容的视图和操作(我不太习惯于概念习语)。

这是我要修改的代码部分:

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

1 回答 1

1

我首先想到的是你在 inChildrenView和 in 中都有引用数据成员ChildrenView::cursor。这使得这些类型不可分配,这是 range-v3 所要求的。尝试将它们更改为指针或std::reference_wrappers,看看这是否能让你更接近。

于 2017-04-11T21:51:33.953 回答