【发布时间】:2012-04-16 02:02:02
【问题描述】:
lambda 表示法使 stl 算法更易于使用。我仍在学习决定什么时候有用,什么时候回退到老式的 for 循环。 通常,有必要迭代两个(或更多)相同大小的容器,以便相应的元素相关,但由于某种原因没有打包到同一个类中。
使用 for 循环来实现的函数如下所示:
template<typename Data, typename Property>
void foo(vector<Data>& data, vector<Property>& prop) {
auto i_data = begin(data);
auto i_prop = begin(prop);
for (; i_data != data.end(); ++i_data, ++i_prop) {
if (i_prop->SomePropertySatistfied()) {
i_data->DoSomething();
}
}
}
为了使用for_each,我需要一个处理多个范围的版本;类似:
template<typename InputIter1, typename InputIter2, typename Function>
Function for_each_on_two_ranges(InputIter1 first1, InputIter1 last1, InputIter2 first2, Function f) {
for (; first1 != last1; ++first1, ++first2) {
f(*first1, *first2);
}
return f;
}
使用这个版本,上面的代码看起来像这样:
template<typename Data, typename Property>
void foo_two_ranges(vector<Data>& data, vector<Property>& prop) {
for_each_on_two_ranges(begin(data), end(data), begin(prop), [](Data& d, Property& p) {
if (p.SomePropertySatistfied()) {
d.DoSomething();
}
});
}
是否有使用 stl 算法实现相同结果的等效方法?
编辑
我以在 boost::range 上运行的 boost::for_each 的形式找到了我的问题的确切答案。为了完整起见,我添加了答案,并附有示例代码。
【问题讨论】:
-
为什么不直接使用你已经写好的
for_each_two_ranges? -
这对我来说似乎很常见,我认为它已经被某人解决了
-
我认为来自 Boost.Iterator 的
zip_iterator可以满足您的需求。详情请见boost.org/doc/libs/1_49_0/libs/iterator/doc/zip_iterator.html。 -
谢谢celtschk,我相信你是对的。但是使用 zip_iterator 的开销让我倾向于更简单的方案
-
只要迭代器本身是独立的,您就无法合理地将语义抽象到函数中。看起来序列在两个可迭代结构之间具有足够的隐含共性,您可以对某种映射做出假设,但您必须牺牲您所做的事情的通用吸引力以获得一些句法简单性。我想说的是,除非你真的经常这样做,否则你已经提出了一个绰绰有余的解决方案。