我实现了set_union
,set_intersection
和set_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());
}
目标是:
正如您在标记为(1),(2)和(3)的行中所看到的,同一容器用作那些STL算法的输入和输出。假设这些STL算法的通常实现,这段代码可以工作,因为它只写入已经处理过的容器部分。
正如评论中指出的那样,标准不能保证这一点。 set_union
,set_intersection
和set_difference
要求结果范围与其中一个输入范围不重叠。
但是,是否存在破坏代码的STL实现?
如果您的答案是肯定的,请提供三种使用过的STL算法之一的符合规定的实施方案。
答案 0 :(得分:1)
符合要求的实现可以检查set_intersection
的参数1和5是否相等,以及它们是否为您的硬盘格式。
如果违反要求,程序的行为不受标准约束;你的程序生病了。
在某些情况下,UB可能值得冒风险和降低成本(审核所有编译器更改和程序集输出)。我不明白这一点;写你自己的。当您违反要求时,std库提出的任何花哨的优化都可能导致问题,并且您已经注意到天真的实现很简单。
答案 1 :(得分:0)
根据经验,我使用不要写在你正在迭代的容器上。一切都会发生。一般来说,这很奇怪。
正如@Yakk所说,这听起来很糟糕。就是这样。从你的代码库中删除的东西安然入睡。
如果你真的需要这些函数,我建议你自己编写内部循环(例如:std::set_intersection
的内部),以便处理算法运行所需的约束。
我不认为寻求STL实施它不起作用是正确的方法。它听起来不像是一个长期的解决方案。从长远来看:标准应该是您的参考,正如有人已经指出的那样,您的解决方案似乎没有正确处理它。
我的2美分