为什么没有用于set_union等的便利函数,它们采用容器类型而不是迭代器?

Why aren't there convenience functions for set_union, etc, which take container types instead of iterators?

本文关键字:类型 迭代器 set 用于 union 函数 为什么      更新时间:2023-10-16

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?(我找不到)

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

是否有像这样的便利函数隐藏在我没有找到的地方?

不在标准库中。

如果没有,有谁能解释为什么它会被排除在STL之外吗?

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

也许有一个更完整的功能集库在boost?

提振。Range就是这样做的。当然,提振。Range 比这更多。它的算法不接受"容器";它们接受迭代器范围,而STL容器恰好满足这些条件。它们还具有惰性求值,这对性能很有好处。

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

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

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

其中第二个用于在除标准小于之外的排序时使用自定义比较。

如果我们现在为容器添加一组sort,我们得到这些新函数

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

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

如果我们改变其中一个函数的名称来解析这个(sort_range, sort_container?),它将不再方便了。

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

    <
  • 简单代码/gh>
  • 算法可以为指定的容器重载,即可以使用map::find算法代替std::find ->更通用的代码
  • 子范围可以很容易地包装到容器中,就像boost::range
  • 中所做的那样

@Bo Persson指出了一个模棱两可的问题,我认为这是很有道理的。

我认为可能有一个历史原因阻止了这一点,甚至没有真正考虑过。

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

即使委员会还在考虑新特性,并且有人写了一个允许传递容器而不是离散迭代器的提案,并且可以接受地处理了潜在的歧义,我怀疑这个提案也会被拒绝。许多人(尤其是面向c语言的人)认为STL是对标准库的一个巨大的补充。我相当肯定,相当多的人会认为仅仅为了允许传递一个参数而添加(大量)更多的函数/重载/专门化是完全不可接受的。

使用开始&迭代的End元素允许使用非容器类型作为输入。例如:

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

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