我经常发现自己使用依赖于开始迭代器和结束迭代器的std算法。为什么标准不包含以容器作为参数的重载(而不是迭代器)。在标准中是否存在不包含此类内容的技术原因?
template <typename ContainerT, typename ValueT>
typename ContainerT::iterator find(ContainerT& container, const ValueT& value)
{
return std::find(begin(container), end(container), value);
}
搜索整个向量时非常方便。我意识到如果你不想迭代整个容器,仍然需要显式迭代器版本。
std::vector<std::string> v;
v.push_back("foo");
v.push_back("bar");
std::find(v.begin(), v.end(), "bar");
find(v, "bar"); // much nicer! :)
答案 0 :(得分:2)
请点击此处获取一个好答案:STL algorithms: Why no additional interface for containers (additional to iterator pairs)?
(道歉,我不能标记为重复)
答案 1 :(得分:0)
它不适用于数组。例如:
int myArray* = new int[2354];
begin(myArray)
和end(myArray)
并不重要。但是std::find(myArray, myArray + 2354, value)
会起作用。
但是标准允许它使用当前接口正确处理数组。
此外,你并不总是想要在整个容器上使用算法。
它仅适用于2个迭代器之间的间隔,因此您可以在从容器中间开始直到容器中间的位置使用find()
。
答案 2 :(得分:0)
我很惊讶没人提到Boost Range library。它提供了您正在寻找的功能,并且proposals可以添加类似于STL的功能。甚至可能有一个专注于范围的ISO C ++工作组,但我不记得我的头脑。
此外,这是我不同意Kerrek SB的罕见情况之一。将迭代器的抽象级别提高到范围,可以获得很多实用工具,特别是在对它们执行算法之前使用适配器来修改范围。 Boost系列库解释了为什么这是一个如此重要的想法。作为一个简短的例子,考虑一系列你想要访问所指对象的指针。要使用迭代器,您需要执行以下操作:
std::vector<int *> v; // populate with something.
auto begin = boost::make_indirect_iterator(v.begin());
auto end = boost::make_indirect_iterator(v.end ());
std::for_each(begin, end, do_something);
使用范围算法和适配器,我们可以更简洁地表达这一点,我认为,显然:
boost::range::for_each(v | boost::adaptors::indirected, do_something);
当前Boost实现似乎唯一缺少的是像变换和过滤这样的范围适配器还不能很好地与lambda函数配合使用。对于一个从根本上改变了我编码方式的库而言,并没有出价。