在 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 中,您可以执行类似的枚举,但 AFAIK 它需要访问者模式:
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);
}
}
有没有办法做一些更像第一种的方法,函数返回一个可以在外部迭代而不是在内部调用访问者的范围?
(我的意思不是构造 astd::vector<Foo>
并返回它——它应该是一个就地枚举。)
我知道 Boost.Range 库,我怀疑它会参与解决方案,但我对它并不是特别熟悉。
我也知道可以定义自定义迭代器来做这种事情(我也怀疑可能会涉及到答案),但我正在寻找易于编写的东西,理想情况下不会比显示的示例更复杂在这里,并且是可组合的(比如 with _SomeOtherCollection
)。
我更喜欢不需要调用者使用 lambdas 或其他仿函数的东西(因为这只会让它再次成为访问者),尽管我不介意在需要时在内部使用 lambdas(但仍然希望在那里避免它们)。