为什么我不能std :: partition this std :: unordered_map

Why can I not std::partition this std::unordered_map?

本文关键字:std unordered this map partition 不能 为什么      更新时间:2023-10-16

这不会构建,我不了解汇编错误。

#include <unordered_map>
#include <algorithm>
int main()
{
    std::unordered_map<int, size_t> occurences = { { 10, 2 }, { 20, 5 }, { 30, 0 }, { 40, 5 }, { 50, 0 }, { 100, 9 } };
    auto newEnd = std::partition(occurences.begin(), occurences.end(), [](const std::pair<int, size_t> &p)
        {
        return p.second == 0;
        });
    return 0;
}

g 抱怨如下。VS2013更加隐秘。

/usr/local/include/c /6.3.0/bits/stl_pair.h: 'void std :: pair&lt; _t1,_t2> :: swap(std :: pair&lt&lt; _t1,_t2>&amp;)[带有_t1 = const int;_t2 =长unsigned int]': /USR/local/include/c /6.3.0/bits/stl_pair.h:473:7:需要 'void std :: swap(std :: pair&lt; _t1,_t2>&amp;,std :: pair&lt&lt; _t1,_t2>&amp;)[带有_t1 = const int;_t2 =长unsigned int]'/usr/local/include/c /6.3.0/bits/stl_algobase.h:148:11:必需 来自'void std :: iter_swap(_forwarditerator1,_ forwarditerator2)[with with with _ forwarditerator1 = std :: __详细:: _ node_iterator,false,false>;_ forwarditerator2 = std :: __详细信息:: _ node_iterator, false,false>]'/usr/local/include/c 6.3.0/bits/stl_algo.h:1500:20: '_ forwarditerator std :: __ partition(_ forwarditerator,, _ forwarditerator,_predicate,std :: forffer_iterator_tag)[带有_forwardIterator = std :: __详细信息:: _ node_iterator,false,false,false>;_predicate = main()::&amp;)>]' /USR/local/include/c /6.3.0/bits/stl_algo.h:4524:30:需要 '_ _biter std :: partition(_biter,_biter,_predicate)[with _biter = std :: __详细信息:: _ node_iterator, false,false>;_predicate = main()::&amp;)>]'main.cpp:12:4:从这里需要 /USR/local/include/c /6.3.0/bits/stl_pair.h:416:6:错误:无匹配 呼叫'交换的函数(const int&amp; const int&amp;)'交换 __p.first);

在这里看到它在Coliru上

据我所知,这张地图满足了cppreference.com上列出的STD ::分区类型要求,所以我很困惑。我的问题是为什么不建立?

错误是因为 mapunordered_map的元素是 std::pair<const Key, value> not std::pair<Key, Value>,因此您不能使用 std::partition之类的算法来重新排序它们,因为const Key无法修改:

error: no matching function for call to 'swap(const int&, const int&)'

只有地图本身才能重新排序元素,并且可以将它们保持在任何需要的顺序上,以维持其不变性。如果您重新排序它们,您将破坏地图的内部数据结构。

std::partition会重新定位提供的容器中的元素,但是您无法重新排序 std::map的元素 - 它具有预定的 filex fixed 其元素的顺序。该标准可以保证,在地图的元素上迭代时,您将始终以越来越多的顺序迭代它们。

正如您在标题中提到的unordered_map,我还将提到,与map不同,它不能保证其元素的顺序,但也无法重新排序其元素。毕竟unordered_map均为无序,因此它永远不会保证您在其元素上迭代的顺序。

所有其他答案都是正确的。unordered_map不能像map那样重新排列其元素,仅此而已。但是有一个更深的概念问题。

创建unordered_map时,您决定订单(任何订单)都不重要,突然间,您希望订单重要(分区操作)。如果您想要一个范围,这肯定需要您的元素在其他容器中,其中一个分区顺序很重要。

您始终可以将分区转换为比较标准,在这种情况下,您可以使用multiset存储收藏的新版本。

#include<algorithm>
#include<unordered_map>
#include<set>
using std::cout; using std::cerr;
int main(){
    std::unordered_map<int, size_t> occurences = { { 10, 2 }, { 20, 5 }, { 30, 0 }, { 40, 5 }, { 50, 0 }, { 100, 9 } };
    auto null_second_pred = [](auto& e){return e.second == 0;};
    auto null_second_comp = [&](auto& a, auto& b){return null_second_pred(a) and (not null_second_pred(b));};
    std::multiset<std::pair<int, size_t>, decltype(null_second_comp)> 
        occurences2(occurences.begin(), occurences.end(), null_second_comp);
    assert( std::is_partitioned(occurences2.begin(), occurences2.end(), null_second_pred) );
}

(更概念上,您可以将元素移至新容器中,但在这种情况下不会有所作为。另外,您不能使用multimap,因为您会丢失信息,并且订购标准不能在这对的第二部分中。)