[英]Why doesn't type deduction work for my set intersection and set difference invocations?
I am trying to write a small algorithm that finds the common and unique parts of two sets and I want to write it in a generic fashion so I have this little example: 我正在尝试写一个小的算法来找到两个集合的公共和唯一部分,我想以一种通用的方式编写它,所以我有一个小例子:
#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());
}
My question is that why does this function fail to compile? 我的问题是为什么该函数无法编译? I tried gcc, clang and MSVC and they all fail.
我尝试了gcc,clang和MSVC,但它们都失败了。 Clang's error message can be inspected here:
可以在此处检查Clang的错误消息:
https://godbolt.org/g/gFZyzo https://godbolt.org/g/gFZyzo
Thanks a lot. 非常感谢。
You need to utilize inserter
because iterators of set
itself are always const iterators that don't allow value modification: 您需要利用
inserter
因为set
本身的迭代器始终是不允许值修改的const迭代器:
... associative containers where the value type is the same as the key type, both
iterator
andconst_iterator
are constant iterators...值类型与键类型相同的关联容器,
iterator
和const_iterator
均为常量迭代器
#include <tuple>
#include <set>
#include <algorithm>
#include <iterator>
template <
typename InputIt,
typename Value = typename std::iterator_traits<InputIt>::value_type>
std::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());
}
The reason is that std::set
's usual iterator - the one you get with begin()
- is not intended for insertion or deletion, only for traversal of what's in the set. 原因是
std::set
的常用迭代器( 使用begin()
获得的迭代器begin()
不打算插入或删除,仅用于遍历集合中的内容。 Try an std::inserter
instead: 尝试使用
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());
}
Note, though, that: 但是请注意:
set_difference
and set_intersection
actually work on ranges rather than sets. set_difference
和set_intersection
实际上可以在范围而不是集合上工作。 std::set
s are kept in-order by default. std::set
保持顺序 。 Do you need them to be ordered before and after running this code? set_difference
and set_intersection
. set_difference
和set_intersection
必须使用有序容器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.