C++ 集_差、集_交和集_并的就地版本

C++ 集_差、集_交和集_并的就地版本,c++,algorithm,stl,C++,Algorithm,Stl,我实现了set\u union、set\u intersection和set\u difference的版本,它们接受一个已排序的容器和一个已排序的范围(不能在容器内),并将操作结果写入容器 template<class Container, class Iter> void assign_difference(Container& cont, Iter first, Iter last) { auto new_end = std::set_difference( /

我实现了
set\u union
set\u intersection
set\u difference
的版本,它们接受一个已排序的容器和一个已排序的范围(不能在容器内),并将操作结果写入容器

template<class Container, class Iter>
void assign_difference(Container& cont, Iter first, Iter last)
{
    auto new_end = std::set_difference( // (1)
        cont.begin(), cont.end(), first, last, cont.begin());
    cont.erase(new_end, cont.end());
}

template<class Container, class Iter>
void assign_intersection(Container& cont, Iter first, Iter last)
{
    auto new_end = std::set_intersection( // (2)
        cont.begin(), cont.end(), first, last, cont.begin());
    cont.erase(new_end, cont.end());
}

template<class Container, class Iter>
void assign_union(Container& cont, Iter first, Iter last)
{
    auto insert_count = last - first;
    cont.resize(cont.size() + insert_count); // T must be default-constructible
    auto rfirst1 = cont.rbegin() + insert_count, rlast1 = cont.rend();
    auto rfirst2 = std::make_reverse_iterator(last);
    auto rlast2 = std::make_reverse_iterator(first);
    rlast1 = std::set_union( // (3)
        rfirst1, rlast1, rfirst2, rlast2, cont.rbegin(), std::greater<>());
    cont.erase(std::copy(rlast1.base(), cont.end(), cont.begin()), cont.end());
}
模板
无效分配(容器和容器,Iter优先,Iter最后)
{
自动新建结束=标准::设置差异(//(1)
cont.begin(),cont.end(),first,last,cont.begin());
继续擦除(新的结束,继续结束());
}
模板
无效分配交叉点(容器和容器,Iter优先,Iter最后)
{
自动新建端点=标准::设置交点(//(2)
cont.begin(),cont.end(),first,last,cont.begin());
继续擦除(新的结束,继续结束());
}
模板
无效分配联合(容器和容器,Iter优先,Iter最后)
{
自动插入计数=最后一次-第一次;
cont.resize(cont.size()+insert_count);//T必须是默认可构造的
自动rfirst1=cont.rbegin()+插入计数,rlast1=cont.rend();
auto rfirst2=std::make_reverse_迭代器(last);
auto rlast2=std::make_reverse_迭代器(第一);
rlast1=std::set_并集(//(3)
rfirst1,rlast1,rfirst2,rlast2,cont.rbegin(),std::greater());
cont.erase(std::copy(rlast1.base()、cont.end()、cont.begin()、cont.end());
}
目标是:

  • 如果容器具有足够的容量来保存结果,则不执行分配
  • 否则,只执行一次分配,为容器提供容纳结果的容量
正如您在标记为(1)、(2)和(3)的行中所看到的,相同的容器被用作这些STL算法的输入和输出。假设这些STL算法的常规实现,这段代码可以工作,因为它只写入容器中已经处理过的部分

正如评论中所指出的,标准并不能保证这是可行的<代码>设置联合,
设置交叉
设置差异
要求结果范围不与其中一个输入范围重叠。 但是,是否有STL实现会破坏代码?


如果您的答案是肯定的,请提供三种使用的STL算法中破坏代码的一种的一致性实现。

一致性实现可以检查
集合交集的参数1和5是否相等,以及它们是否格式化了您的硬盘

如果您违反了要求,您的程序行为不受标准约束;你的程序格式不正确


在某些情况下,UB可能值得承担风险和成本(审核所有编译器更改和程序集输出)。我看不出这有什么意义;写你自己的。std库提出的任何奇特的优化都可能会在您违反需求时导致问题,正如您所注意到的,这种幼稚的实现非常简单。

我使用的经验法则是不要在您正在迭代的容器上编写。一切都可能发生。总的来说,这很奇怪

正如@Yakk所说,这听起来很糟糕。就这样。要从代码库中删除的内容可以让您平静地入睡

如果您确实需要这些函数,我建议您自己编写内部循环(例如:
std::set_intersection
)以处理算法工作所需的约束

我不认为寻找一个STL实现是正确的方法。这听起来不像是一个长期的解决方案。从长远来看:标准应该是你的参考,正如有人已经指出的,你的解决方案似乎没有正确处理它


我的2美分

即使今天的一致性实现没有破坏代码,如果标准中没有保证,那么简单地升级编译器可能会导致代码破坏。甚至不同的优化设置或任何其他编译器标志。我认为您必须提供自己的实现来确保tbh。这些算法的实现只需要几行代码,因此,您可以编写一个破坏代码的标准。我的标准副本中有以下所有这些算法的文本:
要求:生成的范围不得与原始范围重叠。
我认为您不能保证这是有效的。