C# では、カスタム列挙を非常に簡単に定義できます。たとえば、次のようになります。
public IEnumerable<Foo> GetNestedFoos()
{
foreach (var child in _SomeCollection)
{
foreach (var foo in child.FooCollection)
{
yield return foo;
}
foreach (var bar in child.BarCollection)
{
foreach (var foo in bar.MoreFoos)
{
yield return foo;
}
}
}
foreach (var baz in _SomeOtherCollection)
{
foreach (var foo in baz.GetNestedFoos())
{
yield return foo;
}
}
}
(これは、LINQ とより優れたカプセル化を使用して簡略化できますが、それは問題のポイントではありません。)
C++11 では、同様の列挙を行うことができますが、代わりにビジター パターンが必要です。
template<typename Action>
void VisitAllFoos(const Action& action)
{
for (auto& child : m_SomeCollection)
{
for (auto& foo : child.FooCollection)
{
action(foo);
}
for (auto& bar : child.BarCollection)
{
for (auto& foo : bar.MoreFoos)
{
action(foo);
}
}
}
for (auto& baz : m_SomeOtherCollection)
{
baz.VisitAllFoos(action);
}
}
内部でビジターを呼び出すのではなく、関数が外部で反復できる範囲を返す最初のようなことを行う方法はありますか?
(そして、 a を作成しstd::vector<Foo>
て返すという意味ではありません。インプレース列挙である必要があります。)
Boost.Range ライブラリがソリューションに関与していると思われることは知っていますが、特に詳しくはありません。
この種のことを行うためにカスタムイテレータを定義することが可能であることも認識しています(これも答えに関係していると思われます)が、書きやすいもの、理想的には示されている例よりも複雑ではないものを探していますここにあり、構成可能です(のように_SomeOtherCollection
)。
必要に応じて内部でラムダを使用することは気にしませんが (ただし、ラムダを使用することは避けたいと思います)。