如何使用range-v3创建view_facade

时间:2017-04-11 19:53:13

标签: c++ c++11 c++14 range-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;
    });
}

当然,让它可以用于处理与前向范围兼容的视图和动作(我不习惯于概念习语)。

这是我想要改编的代码的一部分:

// 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 个答案:

答案 0 :(得分:1)

第一件事就是我在ChildrenViewChildrenView::cursor都有参考数据成员。这使得这些类型不可分配,范围-v3要求。尝试将它们更改为指针或std::reference_wrapper s,看看是否能让你更接近。