Ключові значення елементів у a std::setє constз поважної причини. Змінення їх може зруйнувати порядок, який є важливим для а std::set.
Отже, рішення - стерти ітератор і вставити новий ключ *it - sub. Зверніть увагу, що std::set::erase()повертає новий ітератор, який потрібно використовувати у вашому випадку, щоб цикл у той час працював належним чином.
#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 }
Демонстрація демо на колиру