2013-04-27 13 views
7

Il seguente codice:Perché std :: remove non funziona con 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); 
} 

non compila con 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>()' 

così sono andato alla definizione di fset::iterator e ho trovato questo nella implementazione di GCC (file ../c++/4.7/bits/stl_set.h, da 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; 

Perché entrambe le definizioni sono costanti? Perché il mio (piuttosto semplice) codice non funziona?

+0

cosa stai cercando di fare? Per rimuovere un singolo elemento basta usare cancellate http://www.cplusplus.com/reference/set/set/erase/ – marcadian

+3

C'è un trucco nel nome: 'remove' non rimuove gli elementi. Li sposta alla fine dell'intervallo. Questo è assolutamente impossibile con un contenitore ordinato. – pmr

+0

@marcadian Questo è solo un esempio per illustrare il mio problema. Il mio vero problema riguarda più codice, con 'remove_if' e un predicato, ma il problema è lo stesso. –

risposta

14

std::set viene ordinato contenitore, mentre std::remove cambia l'ordine degli elementi nel contenitore posizionando gli elementi che devono essere rimossi fino alla fine, quindi non può essere utilizzato con i contenitori ordinati in cui l'ordine degli elementi è definito dal predicato. È necessario utilizzare:

s.erase(1); 

Per rimuovere 1 dal set.

Problemi correlati