如何使用范围 v3 创建view_facade

How to create a view_facade using range-v3

本文关键字:view facade 创建 v3 使用范围      更新时间:2023-10-16

我正在研究一个分层的实体组件系统。它被称为分层 因为一个实体可能由多个实体组成。

我的层次结构是作为几个链表实现的。虽然,我不依赖几个std::liststd::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;
};

我跳出的第一件事是您在ChildrenViewChildrenView::cursor中都有参考数据成员。这使得这些类型不可分配,而范围 v3 需要分配这些类型。尝试将它们更改为指针或std::reference_wrapper,看看这是否会让您更接近。