Ключевые значения элементов в a std::setявляются constвеской причиной. Изменение их может разрушить порядок, который необходим для std::set.
Следовательно, решение состоит в том, чтобы стереть итератор и вставить новый с ключом *it - sub. Обратите внимание, что std::set::erase()возвращается новый итератор, который должен использоваться в вашем случае, чтобы цикл while работал правильно.
#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';
}
Вывод:
test: { 11, 12, 13, 14, 15 }
test: { 1, 2, 3, 4, 5 }
Живая Демо на Колиру
Изменения во std::setвремя итерации по нему не являются проблемой в целом, но могут вызвать тонкие проблемы.
Наиболее важным фактом является то, что все используемые итераторы должны быть сохранены или могут больше не использоваться. (Вот почему текущему итератору элемента стирания присваивается возвращаемое значение, std::set::erase()которое является либо неповрежденным итератором, либо концом набора.)
Конечно, элементы могут быть вставлены также за текущим итератором. Хотя это не проблема, std::setэто может нарушить цикл моего примера выше.
Чтобы продемонстрировать это, я немного изменил приведенный выше пример. Пожалуйста, обратите внимание, что я добавил дополнительный счетчик для предоставления завершения цикла:
#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';
}
Вывод:
test: { 11, 12, 13, 14, 15 }
test: { 23, 24, 25, 31, 32 }
Живая Демо на Колиру