STL算法是否可以使用整个容器作为参数,而不是使用.begin()和.end()?

19

独立的STL算法(例如std::count_if)需要一对迭代器。在我使用这些算法的所有情况(以及我在网上看到的所有示例!)中,我发现自己总是要输入:

独立的STL算法(如std::count_if)需要一对迭代器。在我使用这些算法的所有情况(以及我在网上看到的所有示例!)中,我发现自己总是要输入

std::count_if(myContainer.begin(),myContainer.end(), /* ... */ );

是否有理由使用以下风格的简写模板:

```html
{{ someVariable }}
```

而不是:

```html
<%= someVariable %>
```

两种方式都可以工作,但是似乎更流行使用第一种。有人知道为什么吗?

std::count_if(myContainer, /* ... */ );

在执行操作时通常是整个容器都被操作,因此不提供单独的方法是吗?我是否忽视了它?C++11和C++03的答案是否不同?


2
这只是一个设计决策。许多人并不认为这是一个好选择(请参见http://www.slideshare.net/rawwell/iteratorsmustgo)。Boost使用它们的范围概念提供了这些算法。 - visitor
1
在C++20中,问题已经解决了(https://en.cppreference.com/w/cpp/ranges) - PiotrNycz
4个回答

10

Herb Sutter的一篇不错的博客文章讨论了这个问题。要点是,如果存在与该算法具有相同数量的模板参数的重载,添加基于容器的算法重载可能会创建歧义。Concepts被设计用来解决这个问题。


好的,那么std::count_if_all或者std::count_all_if可以胜任这个工作吗?对于std::sort(std::sort_all)和其他所有函数也是一样的。 - Alexander Riccio

3

STL的原则和灵活性主要是因为操作迭代器而不是容器。这并不是一个大问题,您可以重复使用我早年C语言时使用的技巧:

#define FULL_RANGE(c) (c).begin(), (c).end()

std::copy(FULL_RANGE(c), std::ostream_iterator<c::value_type>(cout, "\n")); 

其实那是个聪明的技巧,虽然我可能会称之为ALL,并且现在使用std :: begin和std :: end。 - André

2

一个原因可能是为了提供迭代器范围的灵活性。有时您可能不需要遍历所有元素:

<iterator> it = myContainer.begin();
it++; // do something
it++; // do something
...
std::count_if(it, myContainer.end(), /* ... */ );

此外,您总是可以拥有一个包装器来为您完成此操作:
template<typename T>
... count_if (T myContainer, ...)
{
  std::count_if(myContainer.begin(), myContainer.end(), /* ... */ );
}

2
在C++11中,使用begin(myContainer)end(myContainer)可以使它适用于数组。 - Sjoerd
3
在需要遍历容器的一部分的情况下,这种0.1%的情况会证明输入“ .begin()”和“ .end()”是有道理的。99.9%的情况下,如果两个都可能存在,则可键入它们。 - eudoxos
2
@Euxodos:是的,那0.1%的情况可以用count_if(make_range(it, myContainer.end()), /*...*/);轻松解决。- 历史上看,算法似乎是匆忙添加到标准库中的,而迭代器在当时是一种新颖的想法。如果他们对它们有更多的经验,事情可能会有所不同。但现在似乎他们无法放弃旧事物,并且无法添加新事物,除非可以干净地完成。 - UncleBens

-1

这是因为STL算法使用迭代器与容器进行连接/交互。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接