簡體   English   中英

為什么我不能 std::partition 這個 std::unordered_map?

[英]Why can I not std::partition this std::unordered_map?

這不會構建,我不明白編譯錯誤。

#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<_T1, _T2>::swap(std::pair<_T1, _T2>&) [with _T1 = 常量整數; _T2 = long unsigned int]': /usr/local/include/c++/6.3.0/bits/stl_pair.h:473:7: 來自 'void std::swap(std::pair<_T1, _T2>& , std::pair<_T1, _T2>&) [與 _T1 = const int; _T2 = long unsigned int]' /usr/local/include/c++/6.3.0/bits/stl_algobase.h:148:11: 來自 'void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = std:: __detail::_Node_iterator, false, false>; _ForwardIterator2 = std::__detail::_Node_iterator, false, false>]' /usr/local/include/c++/6.3.0/bits/stl_algo.h:1500:20: 來自'_ForwardIterator std::__partition(_ForwardIterator, _ForwardIterator, _Predicate, std::forward_iterator_tag) [with _ForwardIterator = std::__detail::_Node_iterator, false, false>; _Predicate = main()::&)>]' /usr/local/include/c++/6.3.0/bits/stl_algo.h:4524:30:來自'_BIter std::partition(_BIter, _BIter, _Predicate) [與 _BIter = std::__detail::_Node_iterator, false, false>; _Predicate = main()::&)>]' main.cpp:12:4: 從這里需要 /usr/local/include/c++/6.3.0/bits/stl_pair.h:416:6: 錯誤:不匹配函數調用'swap(const int&, const int&)' swap(first, __p.first);

在這里看到它在 Coliru 上的直播

據我所知,這張地圖符合cppreference.com 上列出的 std::partition 類型要求,所以我很難過。 我的問題是為什么它不建立?

錯誤是因為mapunordered_map的元素是std::pair<const Key, value>而不是std::pair<Key, Value> ,因此您無法使用std::partition類的算法對它們重新排序因為無法修改const Key

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

只有映射本身可以對元素重新排序,並將它們保持在它需要的任何順序以保持其不變量。 如果您重新排序它們,您將破壞地圖的內部數據結構。

std::partition對提供的容器中的元素重新排序,但是您不能對std::map的元素重新排序 - 它的元素具有預定義的固定順序。 該標准保證在迭代地圖元素時,您將始終按遞增順序迭代它們。

正如您在標題中提到的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因為您會丟失信息,並且排序標准不能位於第二部分一對。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM