映射和向量上的std::set_difference会引发转换错误



下面的代码应该计算地图和矢量的差异

std::map<int, int> cursorMap;
QVector<User> userList;
...
std::vector<int> offlineUserIds{};
std::vector<int>::iterator it;
it = std::set_difference(cursorMap.begin(), cursorMap.end(), userList.begin(), userList.end(), offlineUserIds.begin(),
[](const std::pair<int, int> &e, const User &u){ return u.getId() == e.first; });

在调用set_difference之前,将userList转换为std::vector并进行排序。问题是它给了我以下错误:

error: cannot convert 'std::pair<const int, int>' to 'int' in assignment
...
error: no match for call to '(TextEditor::updateCursorMap(QVector<User>)::<lambda(const std::pair<int, int>&, const User&)>) (User&, std::pair<const int, int>&)'
{ return bool(_M_comp(*__it1, *__it2)); }
...
note: candidate: 'TextEditor::updateCursorMap(QVector<User>)::<lambda(const std::pair<int, int>&, const User&)>'
...
it = std::set_difference(cursorMap.begin(), cursorMap.end(), userList.begin(), userList.end(), offlineUserIds.begin(), [](const std::pair<int, int> &e, const User &u){ return u.getId() == e.first; });
...
note:   no known conversion for argument 1 from 'User' to 'const std::pair<int, int>&'

编辑:

我尝试了以下代码

std::map<int, int> cursorMap;
QVector<User> userList;
...
std::vector<std::pair<int, int>> offlineUserIds{};
std::vector<std::pair<int, int>>::iterator it;
it = std::set_difference(cursorMap.begin(), cursorMap.end(), userList.begin(), userList.end(), offlineUserIds.begin(), [](const std::pair<int, int> &e, const User &u){ return e.first < u.getId(); });

但现在它给了我

note: candidate: 'TextEditor::updateCursorMap(QVector<User>)::<lambda(const std::pair<int, int>&, const User&)>'
it = std::set_difference(cursorMap.begin(), cursorMap.end(), userList.begin(), userList.end(), offlineUserIds.begin(), [](const std::pair<int, int> &e, const User &u){ return e.first < u.getId(); });
...
note:   no known conversion for argument 1 from 'User' to 'const std::pair<int, int>&'

第2版:

这里有一个最小的可复制示例:

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
class User {
int id;
public:
int getId() const { return id; }
};

int main() {
std::vector<User> newUserList{};
std::map<int, int> cursorMap{};
std::vector<User> userList = std::vector(newUserList.begin(), newUserList.end());
std::sort(userList.begin(), userList.end(), [](const User &u1, const User &u2) { return u1.getId() < u2.getId(); });
std::vector<std::pair<int, int>> offlineUserIds{};
std::vector<std::pair<int, int>>::iterator it;
it = std::set_difference(cursorMap.begin(), cursorMap.end(), userList.begin(), userList.end(), offlineUserIds.begin(), [](std::pair<int, int> e, User u){ return e.first < u.getId(); });
return 0;
}

生成输出

In file included from C:/Qt/Tools/mingw810_64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algobase.h:71,
from C:/Qt/Tools/mingw810_64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/char_traits.h:39,
from C:/Qt/Tools/mingw810_64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/ios:40,
from C:/Qt/Tools/mingw810_64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/ostream:38,
from C:/Qt/Tools/mingw810_64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/iostream:39,
from D:asantworkspaceCLionProjectsuntitledmain.cpp:1:
C:/Qt/Tools/mingw810_64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/predefined_ops.h: In instantiation of 'constexpr bool __gnu_cxx::__ops::_Iter_comp_iter<_Compare>::operator()(_Iterator1, _Iterator2) [with _Iterator1 = __gnu_cxx::__normal_iterator<User*, std::vector<User> >; _Iterator2 = std::_Rb_tree_iterator<std::pair<const int, int> >; _Compare = main()::<lambda(std::pair<int, int>, User)>]':
C:/Qt/Tools/mingw810_64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algo.h:5343:17:   required from '_OutputIterator std::__set_difference(_InputIterator1, _InputIterator1, _InputIterator2, _InputIterator2, _OutputIterator, _Compare) [with _InputIterator1 = std::_Rb_tree_iterator<std::pair<const int, int> >; _InputIterator2 = __gnu_cxx::__normal_iterator<User*, std::vector<User> >; _OutputIterator = __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int> > >; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<main()::<lambda(std::pair<int, int>, User)> >]'
C:/Qt/Tools/mingw810_64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/stl_algo.h:5447:46:   required from '_OIter std::set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare) [with _IIter1 = std::_Rb_tree_iterator<std::pair<const int, int> >; _IIter2 = __gnu_cxx::__normal_iterator<User*, std::vector<User> >; _OIter = __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int> > >; _Compare = main()::<lambda(std::pair<int, int>, User)>]'
D:asantworkspaceCLionProjectsuntitledmain.cpp:21:188:   required from here
C:/Qt/Tools/mingw810_64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/predefined_ops.h:143:18: error: no match for call to '(main()::<lambda(std::pair<int, int>, User)>) (User&, std::pair<const int, int>&)'
{ return bool(_M_comp(*__it1, *__it2)); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:/Qt/Tools/mingw810_64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/predefined_ops.h:143:18: note: candidate: 'bool (*)(std::pair<int, int>, User)' <conversion>
C:/Qt/Tools/mingw810_64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/predefined_ops.h:143:18: note:   candidate expects 3 arguments, 3 provided
D:asantworkspaceCLionProjectsuntitledmain.cpp:21:156: note: candidate: 'main()::<lambda(std::pair<int, int>, User)>'
it = std::set_difference(cursorMap.begin(), cursorMap.end(), userList.begin(), userList.end(), offlineUserIds.begin(), [](std::pair<int, int> e, User u){ return e.first < u.getId(); });
                                                                                      ^
D:asantworkspaceCLionProjectsuntitledmain.cpp:21:156: note:   no known conversion for argument 1 from 'User' to 'std::pair<int, int>'
mingw32-make.exe[3]: *** [CMakeFilesuntitled.dirbuild.make:82: CMakeFiles/untitled.dir/main.cpp.obj] Error 1
mingw32-make.exe[2]: *** [CMakeFilesMakefile2:95: CMakeFiles/untitled.dir/all] Error 2
mingw32-make.exe[1]: *** [CMakeFilesMakefile2:102: CMakeFiles/untitled.dir/rule] Error 2
mingw32-make.exe: *** [Makefile:137: untitled] Error 2

因为我不知道的原因:

类型Type1和Type2必须使得InputIt1类型的对象和InputIt2可以被取消引用并,然后隐式地转换为两者类型1和类型2

请参阅cppreference。参数下的最后一句话->comp。由我强调。

模板类std::map的值类型定义为类似

typedef pair<const Key, T> value_type;

然而,类std::vector<int>的值类型是int

不能将类型为std::pair的对象分配给类型为int的对象。

因此编译器会发出一个错误。

此外,可以使用任何顺序的传递参数来调用比较函数。因此,编译器可能再次发出错误,即使用了无效参数,因为参数的类型不同,并且没有从一种类型到另一种类型的隐式转换。。

您可能想要滚动自己的差异函数,或者为User提供转换运算符,允许set_difference比较对和User。

set_difference需要相互转换,并能够将Type1插入到输出序列中。使用std::map时,相互转换是不可能的,因为在这种情况下转换运算符必须是std::pair的成员。

set_difference的比较器cmp是LessCompare,等效性将用类似于:

pair<int, int> e == User u <==> !(e < u) && !(u < e) <==> !cmp(e,u) && !cmp(u,e)

只有当eu可以相互转换时,这才会起作用,但事实并非如此。

我认为您的lambda以错误的顺序获取参数。试试下面的那个。

[](const User &u, const std::pair<int, int> &e){ return u.getId() == e.first; });

最新更新