2010-09-25 16 views
14

¿Alguien me puede ayudar aquí?Borrar idioma eliminar con std :: conjunto error con error relacionado con constness

Compilar este código:

void test() 
{ 
    std::set<int> test; 
    test.insert(42); 
    test.erase(std::remove(test.begin(), test.end(), 30), test.end()); // <- Line 33 
} 

genera el siguiente error al compilar:

$ make 
g++ -c -Wall -pedantic-errors -Wextra -Wunused -Werror a_star.cpp 
/usr/lib/gcc/i686-pc-cygwin/4.3.4/include/c++/bits/stl_algo.h: In function `_FIter std::remove(_FIter, _FIter, const _Tp&) [with _FIter = std::_Rb_tree_const_iterator<int>, _Tp = int]': 
a_star.cpp:33: instantiated from here 
/usr/lib/gcc/i686-pc-cygwin/4.3.4/include/c++/bits/stl_algo.h:779: error: assignment of read-only location `__result.std::_Rb_tree_const_iterator<_Tp>::operator* [with _Tp = int]()' 
make: *** [a_star.o] Error 1 

Respuesta

22

En std::set, los elementos no son modificables. Entonces, el std::set::iterator tampoco es modificable. De this tutorial, sección 27.3.2.1:

En recipientes asociativas simples, donde los elementos son las claves, los elementos son completamente inmutable; el iterador de tipos anidados y const_iterator son por lo tanto los mismos.

Por lo tanto, la expresión erase-remove no se puede aplicar como está. Debe escribir un bucle for y utilizar la función de miembro std::set::erase dentro de él. Ver este question y este aceptó answer y otro answer para detalles exactos, pero en resumen, el bucle es como la siguiente

typename std::set::iterator set_iter; 

for(set_iter it = s.begin(); it != s.end(); /* blank */) { 
    if(some_condition()) { 
     s.erase(it++);  // Note the subtlety here 
    } 
    else { 
     ++it; 
    } 
} 
0

Si recuerdo bien, std :: remove nunca debe ser usado con un std :: set elemento.

Como un conjunto no es una matriz pura, debe usar borrar.

5

modismo Erase-remove no puede ser utilizado con contenedores asociativos. Los contenedores asociativos no permiten modificaciones de todo el elemento del contenedor a través del iterador, lo que significa inmediatamente que las operaciones de secuencia de mutación (como std::remove) no se pueden aplicar a ellos.

1

Como ya he dicho, su código no funciona porque intenta modificar una secuencia dentro de un contenedor asociativo, pero no puede hacerlo porque esta secuencia es inmutable. Justificación: el conjunto contiene una secuencia ordenada, generalmente en un árbol binario. Si se le permitiera modificarlo, podría dañar el contenedor y el programa fallaría. Por cierto, todavía puede suceder en algunas situaciones.

Puede cambiar el código para esto:

test.erase(30); 

o uso (1) Código de ArunSaha de criterios más complicados.

Cuestiones relacionadas