Os principais valores dos elementos em a std::setsão constpor um bom motivo. Modificá-los pode destruir a ordem que é essencial para a std::set.
Portanto, a solução é apagar o iterador e inserir um novo com a chave *it - sub. Observe que std::set::erase()retorna um novo iterador que deve ser usado no seu caso para manter o loop while funcionando corretamente.
#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';
}
Resultado:
test: { 11, 12, 13, 14, 15 }
test: { 1, 2, 3, 4, 5 }
Demonstração ao vivo no coliru
As alterações std::setdurante a iteração sobre ele não são um problema em geral, mas podem causar problemas sutis.
O fato mais importante é que todos os iteradores usados devem ser mantidos intactos ou não podem mais ser usados. (É por isso que o iterador atual do elemento de apagamento é designado com o valor de retorno std::set::erase()que é um iterador intacto ou o final do conjunto.)
Obviamente, é possível inserir elementos também atrás do iterador atual. Embora isso não seja um problema, std::setele pode quebrar o loop do meu exemplo acima.
Para demonstrá-lo, alterei um pouco a amostra acima. Observe que eu adicionei um contador adicional para conceder o término do loop:
#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';
}
Resultado:
test: { 11, 12, 13, 14, 15 }
test: { 23, 24, 25, 31, 32 }
Demonstração ao vivo no coliru