我正在研究分层实体组件系统。之所以称为层次结构,是因为一个实体可能由多个实体组成。
我的层次结构实现为几个链表。虽然,我不依赖几个std::list
or 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;
};