2012-02-09 30 views
22

tôi muốn loại bỏ các yếu tố (thùng histogram) từ một std::unordered_map (histogram) nhằm thoả mãn một predictate (thùng histogram có zero count) được coi là một biểu thức lambda như sauDi Elements từ một Bản đồ Unordered Thực hiện một Predicate

std::remove_if(begin(m_map), end(m_map), [](const Bin & bin) { return bin.second == 0; }); 

nhưng GCC-4.6.1 phàn nàn như sau

/usr/include/c++/4.6/bits/stl_pair.h:156:2: error: assignment of read-only member ‘std::pair<const unsigned char, unsigned char>::first’ 
/usr/include/c++/4.6/bits/stl_pair.h: In member function ‘std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(std::pair<_T1, _T2>&&) [with _T1 = const unsigned char, _T2 = long unsigned int, std::pair<_T1, _T2> = std::pair<const unsigned char, long unsigned int>]’: 
/usr/include/c++/4.6/bits/stl_algo.h:1149:13: instantiated from ‘_FIter std::remove_if(_FIter, _FIter, _Predicate) [with _FIter = std::__detail::_Hashtable_iterator<std::pair<const unsigned char, long unsigned int>, false, false>, _Predicate = pnw::histogram<V, C, H>::pack() [with V = std::vector<unsigned char>, C = long unsigned int, H = std::unordered_map<unsigned char, long unsigned int, std::hash<unsigned char>, std::equal_to<unsigned char>, std::allocator<std::pair<const unsigned char, long unsigned int> > >]::<lambda(const Bin&)>]’ 
tests/../histogram.hpp:68:13: instantiated from ‘void pnw::histogram<V, C, H>::pack() [with V = std::vector<unsigned char>, C = long unsigned int, H = std::unordered_map<unsigned char, long unsigned int, std::hash<unsigned char>, std::equal_to<unsigned char>, std::allocator<std::pair<const unsigned char, long unsigned int> > >]’ 
tests/../histogram.hpp:85:13: instantiated from ‘void pnw::histogram<V, C, H>::normalize(uint) [with V = std::vector<unsigned char>, C = long unsigned int, H = std::unordered_map<unsigned char, long unsigned int, std::hash<unsigned char>, std::equal_to<unsigned char>, std::allocator<std::pair<const unsigned char, long unsigned int> > >, uint = unsigned int]’ 
tests/../histogram.hpp:121:51: instantiated from ‘H& pnw::histogram<V, C, H>::add(It, It) [with It = __gnu_cxx::__normal_iterator<const unsigned char*, std::vector<unsigned char> >, V = std::vector<unsigned char>, C = long unsigned int, H = std::unordered_map<unsigned char, long unsigned int, std::hash<unsigned char>, std::equal_to<unsigned char>, std::allocator<std::pair<const unsigned char, long unsigned int> > >]’ 
tests/../histogram.hpp:129:55: instantiated from ‘H& pnw::histogram<V, C, H>::add(const V&) [with V = std::vector<unsigned char>, C = long unsigned int, H = std::unordered_map<unsigned char, long unsigned int, std::hash<unsigned char>, std::equal_to<unsigned char>, std::allocator<std::pair<const unsigned char, long unsigned int> > >]’ 
tests/../histogram.hpp:57:60: instantiated from ‘pnw::histogram<V, C, H>::histogram(const V&, pnw::histogram<V, C, H>::TYPE_t) [with V = std::vector<unsigned char>, C = long unsigned int, H = std::unordered_map<unsigned char, long unsigned int, std::hash<unsigned char>, std::equal_to<unsigned char>, std::allocator<std::pair<const unsigned char, long unsigned int> > >]’ 
tests/t_histogram.cpp:38:61: instantiated from ‘void test_dense_histogram() [with T = unsigned char, C = long unsigned int]’ 
tests/t_histogram.cpp:64:5: instantiated from ‘void test_histograms() [with C = long unsigned int]’ 
tests/t_histogram.cpp:200:29: instantiated from here 
/usr/include/c++/4.6/bits/stl_pair.h:156:2: error: assignment of read-only member ‘std::pair<const unsigned char, long unsigned int>::first’ 
make: *** [tests/t_histogram.o] Error 1 

không phải là std::remove_if áp dụng đối với std::unordered_map?

+0

Tôi cũng rơi vào bẫy này, nhưng bây giờ nghĩ về nó std :: loại bỏ (di chuyển các phần tử vào cuối container) không thể làm việc với một thùng chứa kết hợp. "phần cuối của container" không thực sự có ý nghĩa nữa. – RichardBruce

Trả lời

29

Câu trả lời là không (bạn không thể sử dụng remove_if trên các vùng chứa liên kết). Bạn cần phải làm một vòng lặp đơn giản; các erase(iterator) thành viên tại trả về iterator hợp lệ tiếp theo - vì vậy vòng lặp của bạn trở thành:

for(auto it = begin(m_map); it != end(m_map);) 
{ 
    if (it->second == 0) 
    { 
    it = m_map.erase(it); // previously this was something like m_map.erase(it++); 
    } 
    else 
    ++it; 
} 
+0

Cảm ơn. Bây giờ tôi biết. BTW Tôi thực sự khao khát các khái niệm C++ ... –

+0

Tại sao điều này lại có quá nhiều phiếu bầu? Điều này không segv với 1 yếu tố? – cjhanks

+0

@cjhanks, bạn có thể chỉ cho tôi một ví dụ khi nó phân đoạn, tôi sẽ sửa nó .. – Nim

1

a proposal of Uniform Container Erasure bởi Stephan T. Lavavej:

template <class K, class T, class H, class P, class A, class Predicate> 
void erase_if(unordered_map<K, T, H, P, A>& c, Predicate pred); 

tức

std::erase_if(m_map, [](const Bin& bin) { return bin.second == 0; }); 

Đáng tiếc là nó didn' t làm cho nó C++ 17. Tôi cho rằng điều này là gắn liền với việc thông qua các Ranges TS.