要素のキー値が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繰り返し処理中の変更は一般的に問題ではありませんが、微妙な問題を引き起こす可能性があります。
最も重要な事実は、使用されるすべてのイテレータはそのままにしておく必要があるか、もう使用しない可能性があるということです。(それが、erase要素の現在のイテレーターに、戻り値が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 }
コリルのライブデモ