2

std::set_union 及其亲属使用两对迭代器来操作要操作的集合。这很棒,因为它是最灵活的事情。然而,他们可以很容易地制作额外的便利功能,这对于 80% 的典型用途来说会更加优雅。

例如:

template<typename ContainerType, typename OutputIterator>
OutputIterator set_union( const ContainerType & container1, 
                const ContainerType & container2, 
                OutputIterator      & result      )
{
    return std::set_union( container1.begin(), container1.end(), 
                           container2.begin(), container2.end(), 
                           result );
}

会转:

std::set_union( mathStudents.begin(), mathStudents.end(), 
                physicsStudents.begin(), physicsStudents.end(), 
                students.begin() );

进入:

std::set_union( mathStudents, physicsStudents, students.begin() );

所以:

  • 有没有像这样的便利功能隐藏在我还没找到的地方?

  • 如果没有,任何人都可以解释为什么它会被排除在 STL 之外吗?

  • 在 boost 中是否有功能更全的集合库?(我找不到一个)

当然,我总是可以将我的实现放在某个实用程序库中,但是很难将这些东西组织起来,以便在所有项目中使用它们,但又不会不恰当地组合在一起。

4

5 回答 5

8

有没有像这样的便利功能隐藏在我还没找到的地方?

不在标准库中。

如果没有,任何人都可以解释为什么它会被排除在 STL 之外吗?

算法的一般思想是它们与迭代器一起工作,而不是容器。容器可以修改、更改和戳;迭代器不能。因此,您知道,在执行算法之后,它并没有改变容器本身,只是潜在地改变了容器的内容。

在 boost 中是否有功能更全的集合库?

Boost.Range做到了这一点。当然,Boost.Range 的作用远不止于此。它的算法不需要“容器”;它们采用迭代器范围,而 STL 容器恰好满足这些条件。他们也有惰性评估,这对性能很有好处。

于 2011-07-08T07:56:09.237 回答
2

使用迭代器的一个原因当然是它更通用,并且适用于不是容器的范围,或者只是容器的一部分。

另一个原因是签名会混淆。许多算法,例如 std::sort 已经有多个签名:

sort(Begin, End);
sort(Begin, End, Compare);

第二个是用于在标准小于以外的排序时使用自定义比较。

如果我们现在添加一组sortfor 容器,我们会得到这些新功能

sort(Container);
sort(Container, Compare);

现在我们有了两个签名sort(Begin, End)sort(Container, Compare)它们都带有两个模板参数,编译器在解析调用时会遇到问题。

如果我们更改其中一个函数的名称来解决这个问题(sort_range,sort_container?),它将不再那么方便了。

于 2011-07-08T08:37:23.380 回答
1

我同意,STL 应该使用容器而不是迭代器对,原因如下:

  • 更简单的代码
  • 算法可以为指定的容器重载,即可以使用 map::find 算法而不是 std::find -> 更通用的代码
  • 一个子范围可以很容易地被包装到一个容器中,就像在 boost::range 中所做的那样
于 2011-07-08T07:59:54.377 回答
1

@Bo Persson 指出了模棱两可的问题,我认为这是非常有效的。

我认为有一个历史原因可能会阻止它被真正考虑。

STL 在标准化过程中相对较晚地被引入 C++。在它被接受后不久,委员会投票反对甚至考虑将任何新特性添加到 C++98 中(甚至可能在同一次会议上)。当大多数人已经将注意力集中在现有的 STL 上,以至于认识到您可以从范围之类的东西而不是单个迭代器中获得多少便利时,甚至考虑都为时已晚。

即使委员会仍在考虑新功能,并且有人编写了允许传递容器而不是离散迭代器的提案,并且已经可接受地处理了可能存在的歧义,我怀疑该提案也会被拒绝。无论如何,许多人(尤其是面向 C 的人)都将 STL 视为标准库的巨大补充。我有理由肯定,很多人会认为添加(很多)更多功能/重载/专业化只是为了允许传递一个参数而不是两个参数是完全不可接受的。

于 2011-07-08T20:06:42.123 回答
0

使用开始和结束元素进行迭代允许使用非容器类型作为输入。例如:

ContainerType students[10];
vector<ContainerType> physicsStudents;
std::set_union(physicsStudents.begin(), physicsStudents.end(), 
               &students[0], &students[10], 
               physicsStudents.begin());

由于它们是如此简单的实现,我认为不将它们添加到 std 库并允许作者添加自己的实现是有意义的。特别是考虑到它们是模板,因此可能会增加代码的 lib 大小并在 std 中添加便利函数会导致代码膨胀。

于 2011-07-08T07:56:37.127 回答