Tengo dos std::map<>
objetos a
y me b
gustaría mover ( extract
+ insert
) algunos elementos (nodos) de un mapa a otro según algún predicado p
.
for (auto i = a.begin(); i != a.end(); ++i)
if (p(*i))
b.insert(a.extract(i))
Este código se divide en clang. Supongo que el problema es el incremento de i
después de que su nodo se haya extraído de a.
¿Es la forma correcta / única de solucionar esto usando un post-incremento ?, por ejemplo:
for (auto i = a.begin(); i != a.end();)
if (p(*i))
b.insert(a.extract(i++))
else
++i;
EDITAR : eliminé la parte sobre "¿por qué esto funciona en gcc?", Porque no puedo reproducir esto en mi configuración actual. Estoy convencido de que solía hacerlo en algún momento, pero con gcc 9.2.1 obtengo un punto muerto (en lugar de un segfault). De cualquier manera, incrementar después extract()
no funciona.
std::set
ystd::map
son muy similares, y por lo que puedo decirextract
tiene las mismas implicaciones de invalidación queerase
.Respuestas:
En efecto. La extracción invalida los iteradores del elemento extraído, y
i
es ese iterador. El comportamiento de incrementar o indirectamente a través de un iterador no válido no está definido.Porque el comportamiento del programa no está definido.
Es una forma correcta de solucionar esto. No es una manera particularmente mala. Si prefiere no repetir el incremento, un enfoque es usar una variable:
fuente
current
se quedaría en un estado de mudanza . Cualquiera que sea ese estado no importará ya que ya no se usa después de eso.current
utilizando laif (auto current = ++i; p(*current))
sintaxis de c ++ 17s .