我正在尝试编写一个小算法来查找两个集合的共同部分和独特部分,并且我想以通用的方式编写它,所以我有这个小例子:
#include "boost/tuple/tuple.hpp"
#include <set>
template <typename InputIt, typename Value = typename std::iterator_traits<InputIt>::value_type>
boost::tuple<std::set<Value>, std::set<Value>, std::set<Value>>
findUniqueAndCommon(InputIt fbegin, InputIt fend, InputIt sbegin, InputIt send)
{
std::set<Value> setL(fbegin, fend);
std::set<Value> setR(sbegin, send);
std::set<Value> uniqueInCatalog1;
std::set<Value> uniqueInCatalog2;
std::set<Value> commonInBoth;
std::set_difference(setL.begin(), setL.end(), setR.begin(), setR.end(), uniqueInCatalog1.begin());
std::set_difference(setR.begin(), setR.end(), setL.begin(), setL.end(), uniqueInCatalog2.begin());
std::set_intersection(setL.begin(), setL.end(), setR.begin(), setR.end(), commonInBoth.begin());
return{ uniqueInCatalog1, uniqueInCatalog2, commonInBoth };
}
int main()
{
std::set<int> x = {1, 2, 3};
std::set<int> y = {4, 2, 3};
findUniqueAndCommon<std::set<int>::iterator>(x.begin(), x.end(), y.begin(), y.end());
}
我的问题是为什么这个函数编译失败?我尝试了 gcc、clang 和 MSVC,但它们都失败了。可以在此处检查 Clang 的错误消息:
https://godbolt.org/g/gFZyzo
非常感谢。
最佳答案
原因是std::set
的常用迭代器 - the one you get with begin()
- 不适用于插入或删除,仅用于遍历集合中的内容。试试 std::inserter
相反:
#include "boost/tuple/tuple.hpp"
#include <set>
template <typename InputIt, typename Value = typename std::iterator_traits<InputIt>::value_type>
boost::tuple<std::set<Value>, std::set<Value>, std::set<Value>>
findUniqueAndCommon(InputIt fbegin, InputIt fend, InputIt sbegin, InputIt send)
{
std::set<Value> setL(fbegin, fend);
std::set<Value> setR(sbegin, send);
std::set<Value> uniqueInCatalog1;
std::set<Value> uniqueInCatalog2;
std::set<Value> commonInBoth;
std::set_difference(setL.begin(), setL.end(), setR.begin(), setR.end(), std::inserter(uniqueInCatalog1, uniqueInCatalog1.end()));
std::set_difference(setR.begin(), setR.end(), setL.begin(), setL.end(), std::inserter(uniqueInCatalog2, uniqueInCatalog2.end()));
std::set_intersection(setL.begin(), setL.end(), setR.begin(), setR.end(), std::inserter(commonInBoth, commonInBoth.end()));
return{ uniqueInCatalog1, uniqueInCatalog2, commonInBoth };
}
int main()
{
std::set<int> x = {1, 2, 3};
std::set<int> y = {4, 2, 3};
findUniqueAndCommon<std::set<int>::iterator>(x.begin(), x.end(), y.begin(), y.end());
}
不过请注意:
- 您正在创建范围的集合拷贝;我不认为你真的需要那样做。只需使用范围 -
set_difference
和set_intersection
实际上适用于范围而不是集合。 std::set
默认保持有序。您需要在运行此代码之前和之后订购它们吗?如果不是,请考虑选择不同的容器。另一方面,正如@n.m 指出的那样,set_difference
和set_intersection
需要有序的容器。- 您将对这两个集合进行三次迭代而不是一次(您可以使用自定义函数在有序容器上执行此操作)。
- C++ 标准有自己的元组 - std::tuple - 自 C++11 以来。
关于c++ - 为什么类型推导对我的集合交集和集合差异调用不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47621034/