为什么我不能std :: partition这个std :: unordered_map?

时间:2017-02-24 08:24:37

标签: c++ stl-algorithm

这不构建,我不理解编译错误。

#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&gt; :: swap(std :: pair&lt; _T1,_T2&gt;&amp;)[with _T1 =   const int; _T2 = long unsigned int]':   /usr/local/include/c++/6.3.0/bits/stl_pair.h:473:7:从   'void std :: swap(std :: pair&lt; _T1,_T2&gt;&amp;,std :: pair&lt; _T1,_T2&gt;&amp;)[with _T1   = const int; _T2 = long unsigned int]'/usr/local/include/c++/6.3.0/bits/stl_algobase.h:148:11:required   来自'void std :: iter_swap(_ForwardIterator1,_ForwardIterator2)[与   _ForwardIterator1 = std :: __ detail :: _ Node_iterator,false,false&gt ;; _ForwardIterator2 =   的std :: __细节:: _ Node_iterator,   false,false&gt;]'/usr/local/include/c++/6.3.0/bits/stl_algo.h:1500:20:   从'_ForwardIterator std :: __分区(_ForwardIterator,   _ForwardIterator,_Predicate,std :: forward_iterator_tag)[with _ForwardIterator = std :: __ detail :: _ Node_iterator,false,false&gt ;; _Predicate = main()::&amp;)&gt;]'   /usr/local/include/c++/6.3.0/bits/stl_algo.h:4524:30:从   '_BIter std :: partition(_BIter,_BIter,_Predicate)[with _BIter =   的std :: __细节:: _ Node_iterator,   假,假&gt ;; _Predicate = main()::&amp;)&gt;]'main.cpp:12:4:从这里需要   /usr/local/include/c++/6.3.0/bits/stl_pair.h:416:6:错误:没有匹配   函数调用'swap(const int&amp;,const int&amp;)'swap(第一,   __p.first);

See it live on Coliru here

据我所知,这张地图符合cppreference.com上列出的std :: partition类型要求,所以我很难过。我的问题是它为什么不构建?

1 个答案:

答案 0 :(得分:0)

所有其他答案都是正确的。 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,因为这样会丢失信息,并且排序条件也不会在该对的第二部分。)