使用自定义比较器内的容器进行比较

问题描述 投票:0回答:1
#include <set>
#include <string>
#include <unordered_map>
#include <vector>

int main()
{
    std::vector<std::string> wordsContainer={"aba", "baba","ris", "u"};
    auto cmp=[&](int i, int j){
        if (wordsContainer[i].size() != wordsContainer[j].size())
            return wordsContainer[i].size() < wordsContainer[j].size();
        return i < j;
    };
    std::unordered_map<int,std::set<int,decltype(cmp)>>mp;
    mp[0].insert(2);  // <-- this line is the issue
}

我正在尝试在 C++20 中做类似的事情。我希望我的容器根据其他容器进行排序。但是编译器抱怨 cmp 的类型,从 [&] 中删除 & 可以,但我无法访问变量wordsContainer。

In file included from /opt/rh/devtoolset-10/root/usr/include/c++/10/map:60,
                 from /opt/rh/devtoolset-10/root/usr/include/c++/10/x86_64-redhat-linux/bits/stdc++.h:81,
                 from main.cpp:1:
/opt/rh/devtoolset-10/root/usr/include/c++/10/bits/stl_tree.h: In instantiation of ‘std::_Rb_tree_key_compare<_Key_compare>::_Rb_tree_key_compare() [with _Key_compare = main()::<lambda(int, int)>]’:
/opt/rh/devtoolset-10/root/usr/include/c++/10/bits/stl_tree.h:688:22:   required from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Rb_tree_impl<_Key_compare, <anonymous> >::_Rb_tree_impl() [with _Key_compare = main()::<lambda(int, int)>; bool <anonymous> = false; _Key = int; _Val = int; _KeyOfValue = std::_Identity<int>; _Compare = main()::<lambda(int, int)>; _Alloc = std::allocator<int>]’
/opt/rh/devtoolset-10/root/usr/include/c++/10/bits/stl_tree.h:935:7:   required from ‘constexpr std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>) [with _Args1 = {int&&}; long unsigned int ..._Indexes1 = {0}; _Args2 = {}; long unsigned int ..._Indexes2 = {}; _T1 = const int; _T2 = std::__debug::set<int, main()::<lambda(int, int)> >]’
/opt/rh/devtoolset-10/root/usr/include/c++/10/tuple:1678:63:   required from ‘constexpr std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>) [with _Args1 = {int&&}; _Args2 = {}; _T1 = const int; _T2 = std::__debug::set<int, main()::<lambda(int, int)> >]’
/opt/rh/devtoolset-10/root/usr/include/c++/10/bits/stl_construct.h:97:14:   required from ‘constexpr decltype (::new(void*(0)) _Tp) std::construct_at(_Tp*, _Args&& ...) [with _Tp = std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > >; _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; decltype (::new(void*(0)) _Tp) = std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > >*]’
/opt/rh/devtoolset-10/root/usr/include/c++/10/bits/alloc_traits.h:514:4:   required from ‘static constexpr void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > >; _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Tp = std::_Rb_tree_node<std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > > >; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<std::_Rb_tree_node<std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > > > >]’
/opt/rh/devtoolset-10/root/usr/include/c++/10/bits/stl_tree.h:618:32:   required from ‘void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_construct_node(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type, _Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Key = int; _Val = std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > >; _KeyOfValue = std::_Select1st<std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > > >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > > >*]’
/opt/rh/devtoolset-10/root/usr/include/c++/10/bits/stl_tree.h:635:21:   required from ‘std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_create_node(_Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Key = int; _Val = std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > >; _KeyOfValue = std::_Select1st<std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > > >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > > >*]’
/opt/rh/devtoolset-10/root/usr/include/c++/10/bits/stl_tree.h:2461:33:   required from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_emplace_hint_unique(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator, _Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Key = int; _Val = std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > >; _KeyOfValue = std::_Select1st<std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > > >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree<int, std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > >, std::_Select1st<std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > > >, std::less<int>, std::allocator<std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > > > >::iterator; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator = std::_Rb_tree<int, std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > >, std::_Select1st<std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > > >, std::less<int>, std::allocator<std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > > > >::const_iterator]’
/opt/rh/devtoolset-10/root/usr/include/c++/10/bits/stl_map.h:520:37:   required from ‘std::__cxx1998::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::__cxx1998::map<_Key, _Tp, _Compare, _Alloc>::operator[](std::__cxx1998::map<_Key, _Tp, _Compare, _Alloc>::key_type&&) [with _Key = int; _Tp = std::__debug::set<int, main()::<lambda(int, int)> >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::__debug::set<int, main()::<lambda(int, int)> > > >; std::__cxx1998::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = std::__debug::set<int, main()::<lambda(int, int)> >; std::__cxx1998::map<_Key, _Tp, _Compare, _Alloc>::key_type = int]’
main.cpp:339:9:   required from here
/opt/rh/devtoolset-10/root/usr/include/c++/10/bits/stl_tree.h:149:24: error: use of deleted function ‘main()::<lambda(int, int)>::<lambda>()’
  149 |       : _M_key_compare()
      |                        ^
main.cpp:333:16: note: a lambda closure type has a deleted default constructor
  333 |     auto cmp=[&](int i, int j){
      |                ^

编译器选项:

-std=c++20 -O2 -Wall -Wextra -Wshadow -Wconversion -Wfloat-equal -Wduplicated-cond -W逻辑操作 -Wall -Wextra -O2 -W逻辑操作 -Wshift-overflow -Wduplicated-cond -Wcast -qual -Wcast-align -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDATIC -D_FORTIFY_SOURCE=2 -fno-sanitize-recover -fstack-protector

我也尝试过

std::unordered_map<int,std::set<int,decltype(cmp)>>mp;
但它给出了:

main.cpp:338:21: error: type/value mismatch at argument 2 in template parameter list for ‘template<class _Key, class _Cmp, class _Allocator> class std::__debug::set’
  338 |     map<int,set<int,cmp>>mp;
      |                     ^~~
main.cpp:338:21: note:   expected a type, got ‘cmp’
main.cpp:338:24: error: template argument 2 is invalid
  338 |     map<int,set<int,cmp>>mp;
      |                        ^~
main.cpp:338:24: error: template argument 4 is invalid
main.cpp:339:7: error: invalid types ‘int[int]’ for array subscript
  339 |     mp[0].insert(2);

有办法实现这一点吗?我调查了this,但没有帮助。

c++ lambda comparator
1个回答
0
投票

您不能使用地图的operator[],因为它需要默认构建您的集合。并且你不能默认构造

std::set<int, decltype(cmp)> mySet;
,因为你不能默认构造捕获 lambda 的实例。

您可以使用

insert
: 代替 operator[]

mp.insert(std::make_pair(0, std::set<int, decltype(cmp)>{cmp}));
mp.at(0).insert(2);

但请注意,您的比较器的逻辑可能会被破坏,例如如果您插入的元素大于/等于您的 wordsContainer 的大小,则会导致

未定义的行为

© www.soinside.com 2019 - 2024. All rights reserved.