私は階層的なエンティティコンポーネントシステムで作業しています。エンティティは複数のエンティティで構成されている可能性があるため、階層型 と呼ばれています。range-v3を使用してview_facadeを作成する方法
私の階層構造はいくつかのリンクリストとして実装されています。しかし、私はいくつかのstd::list
またはstd::forward_list
に頼っていません。実際には、私は2つのベクトルを持っています: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;
};
ありがとうございます。あなたはちょうど問題を持っています。私はstd :: reference_wrapperを動作させるのに十分な時間がありませんでしたが、Cursorのコンセプトでは失敗し続けます。今のところ、私は生のポインタで参照を変更しました。 私は、私の構造がForwardRangeのような特定の概念をモデル化したいと思います。 begin()/ end()メソッドとforward Iteratorを作成する必要がありますか?私はレンジのコンセプトがそのイテレータの定型化を置き換えると考えていたと思った... – csguth
@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