简体   繁体   English

地图上的 std::set_difference 和向量引发转换错误

[英]std::set_difference on map and a vector throws conversion errors

The following code should compute the difference of a map and a vector以下代码应该计算地图和向量的差异

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; });

before invoking set_difference , userList is converted to a std::vector and sorted.在调用set_difference之前, userList被转换为std::vector并排序。 The problem is that it gaves me the following errors:问题是它给了我以下错误:

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>&'

EDIT:编辑:

I tried the following code我尝试了以下代码

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(); });

but now it gives me但现在它给了我

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>&'

EDIT2:编辑2:

Here is a minimal reproducible example:这是一个最小的可重现示例:

#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;
}

build output构建输出

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:\asant\workspace\CLionProjects\untitled\main.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:\asant\workspace\CLionProjects\untitled\main.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:\asant\workspace\CLionProjects\untitled\main.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:\asant\workspace\CLionProjects\untitled\main.cpp:21:156: note:   no known conversion for argument 1 from 'User' to 'std::pair<int, int>'
mingw32-make.exe[3]: *** [CMakeFiles\untitled.dir\build.make:82: CMakeFiles/untitled.dir/main.cpp.obj] Error 1
mingw32-make.exe[2]: *** [CMakeFiles\Makefile2:95: CMakeFiles/untitled.dir/all] Error 2
mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:102: CMakeFiles/untitled.dir/rule] Error 2
mingw32-make.exe: *** [Makefile:137: untitled] Error 2

For a reason that is not known to me:出于我不知道的原因:

The types Type1 and Type2 must be such that objects of types InputIt1 and InputIt2 can be dereferenced and then implicitly converted to both Type1 and Type2 Type1 和 Type2 类型必须使得 InputIt1 和 InputIt2 类型的对象可以被取消引用,然后隐式转换为 Type1 和 Type2

See cppreference .请参阅cppreference Last sentence under Parameters -> comp.参数 -> comp 下的最后一句。 Highlighted by me.由我突出显示。

The value type of the template class std::map is defined like模板类std::map的值类型定义如下

typedef pair<const Key, T> value_type;

However the value type of the class std::vector<int> is int .但是类std::vector<int>的值类型是int

You can not assign an object of the typs std::pair to an object of the type int .您不能将类型为std::pair的对象分配给类型为int的对象。

So the compiler issues an error.所以编译器会报错。

Moreover the comparison function can be called with any order of the passed arguments.此外,可以使用传递参数的任何顺序调用比较函数。 So again the compiler can issue an error that invalid arguments are used because the types of parameters are different and there is no implicit conversion from one type to another..因此,由于参数类型不同,并且没有从一种类型到另一种类型的隐式转换,编译器会再次发出使用无效参数的错误。

You may want either roll own difference function or provide User with conversion operator which would allow set_difference to compare pair and User.您可能想要滚动自己的差异函数或为用户提供转换运算符,这将允许 set_difference 比较对和用户。

set_difference requires mutual conversion and ability to insert Type1 to output sequence. set_difference 需要相互转换和插入 Type1 到输出序列的能力。 With use of std::map mutual conversion is not possible because conversion operator must be member of std::pair in that case.使用std::map相互转换是不可能的,因为在这种情况下转换运算符必须是std::pair成员。

The comparator cmp for set_difference is LessCompare and the equivalence will be checked with something like: set_difference 的比较器cmpLessCompare并且将使用以下内容检查等效性:

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

This will work only if e and u are convertible to each other, which is not the case.这仅在eu可以相互转换时才有效,但事实并非如此。

I believe your lambda is taking parameters in the wrong order.我相信您的 l​​ambda 以错误的顺序获取参数。 Try the one below.试试下面的一个。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM