Los valores clave de los elementos en a std::setson constpor una buena razón. Modificarlos puede destruir el orden que es esencial para a std::set.
Por lo tanto, la solución es borrar el iterador e insertar uno nuevo con la clave *it - sub. Tenga en cuenta que std::set::erase()devuelve un nuevo iterador que debe usarse en su caso para mantener el bucle while funcionando correctamente.
#include<iostream>
#include<set>
template <typename T>
std::ostream& operator<<(std::ostream &out, const std::set<T> &values)
{
const char *sep = "{ ";
for (const T &value : values) { out << sep << value; sep = ", "; }
return out << " }";
}
int main()
{
std::set<int> test{ 11, 12, 13, 14, 15 };
std::cout << "test: " << test << '\n';
const int sub = 10;
std::set<int>::iterator iter = test.begin();
while (iter != test.end()) {
const int value = *iter;
iter = test.erase(iter);
test.insert(value - sub);
}
std::cout << "test: " << test << '\n';
}
Salida:
test: { 11, 12, 13, 14, 15 }
test: { 1, 2, 3, 4, 5 }
Demo en vivo en coliru
Los cambios al std::setiterar sobre él no son un problema en general, pero pueden causar problemas sutiles.
El hecho más importante es que todos los iteradores usados deben mantenerse intactos o ya no pueden usarse. (Es por eso que el iterador actual del elemento de borrado se asigna con el valor de retorno del std::set::erase()cual es un iterador intacto o el final del conjunto).
Por supuesto, los elementos se pueden insertar también detrás del iterador actual. Si bien esto no es un problema relacionado con el std::set, puede romper el ciclo de mi ejemplo anterior.
Para demostrarlo, cambié un poco la muestra anterior. Tenga en cuenta que agregué un contador adicional para otorgar la terminación del ciclo:
#include<iostream>
#include<set>
template <typename T>
std::ostream& operator<<(std::ostream &out, const std::set<T> &values)
{
const char *sep = "{ ";
for (const T &value : values) { out << sep << value; sep = ", "; }
return out << " }";
}
int main()
{
std::set<int> test{ 11, 12, 13, 14, 15 };
std::cout << "test: " << test << '\n';
const int add = 10;
std::set<int>::iterator iter = test.begin();
int n = 7;
while (iter != test.end()) {
if (n-- > 0) {
const int value = *iter;
iter = test.erase(iter);
test.insert(value + add);
} else ++iter;
}
std::cout << "test: " << test << '\n';
}
Salida:
test: { 11, 12, 13, 14, 15 }
test: { 23, 24, 25, 31, 32 }
Demo en vivo en coliru