2013-04-27 3 views
7

Следующий код:Почему std :: remove не работает с std :: set?

#include <iostream> 
#include <set> 
#include <algorithm> 

std::set<int> s; 

int main() 
{ 
    s.insert(1); 
    s.insert(2); 

    std::remove(s.begin(), s.end(), 1); 
} 

не компилируется с GCC 4.7.2:

$ LANG=C g++ test.cpp 
In file included from /usr/include/c++/4.7/algorithm:63:0, 
      from test.cpp:3: 
/usr/include/c++/4.7/bits/stl_algo.h: In instantiation of '_FIter std::remove(_FIter, _FIter, const _Tp&) [with _FIter = std::_Rb_tree_const_iterator<int>; _Tp = int]': 
test.cpp:12:38: required from here 
/usr/include/c++/4.7/bits/stl_algo.h:1135:13: error: assignment of read-only location '__result.std::_Rb_tree_const_iterator<_Tp>::operator*<int>()' 

Так что я пошел к определению fset::iterator, и я нашел это в реализации GCC (файл ../c++/4.7/bits/stl_set.h, от 125):

// _GLIBCXX_RESOLVE_LIB_DEFECTS                                        
    // DR 103. set::iterator is required to be modifiable,                                  
    // but this allows modification of keys.                                      
    typedef typename _Rep_type::const_iterator   iterator; 
    typedef typename _Rep_type::const_iterator   const_iterator; 
    typedef typename _Rep_type::const_reverse_iterator reverse_iterator; 
    typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; 
    typedef typename _Rep_type::size_type     size_type; 
    typedef typename _Rep_type::difference_type   difference_type; 

Почему оба определения постоянны? Почему мой (довольно простой) код не работает?

+0

Что вы пытаетесь сделать? Чтобы удалить один элемент, просто используйте стирание http://www.cplusplus.com/reference/set/set/erase/ – marcadian

+3

В названии есть трюк: 'remove' не удаляет элементы. Он перемещает их до конца диапазона. Это невозможно без заказанного контейнера. – pmr

+0

@marcadian Это только пример, иллюстрирующий мою проблему. Моя настоящая проблема связана с большим количеством кода с 'remove_if' и предикатом, но проблема такая же. –

ответ

14

std::set является заказным контейнером, а std::remove изменяет порядок элементов в контейнерах, которые должны быть удалены до конца, поэтому его нельзя использовать с заказанными контейнерами, где порядок элементов определяется предикатом. Вам необходимо использовать:

s.erase(1); 

Удалить 1 из множества.

 Смежные вопросы

  • Нет связанных вопросов^_^