Есть несколько ответов на StackOverflow, которые свидетельствуют о том, что следующий цикл является прекрасным способом для удаления элементов из std::unordered_map
, удовлетворяющих некоторого предиката pred
:Стирание элементов из unordered_map в цикле
std::unordered_map<...> m;
auto it = m.begin();
while (it != m.end())
{
if (pred(*it))
it = m.erase(it);
else
++it;
}
Я специально заинтересован в C++ 11 (в отличие от C++, 14), а также следующие зловещим note on cppreference.com предполагает, что вышеуказанный цикл, зависит от неопределенного поведения и может не работать в C++ 11 после того, как все:
порядка элементы, которые не стираются, сохраняются (thi s позволяет удалять отдельные элементы во время прохода через контейнер) (с C++ 14)
Смотрите также Title 2356. Stability of erasure in unordered associative containers, который содержит запрошенное изменение формулировки Working Draft N3797 пункта 14 на странице 754 (дополнительная фраза начала ", и сохранить относительный порядок ...").
Данная формулировка относится к N3797.
Изменить [unord.req], P14, как показано:
-14- вкладыш и устанавливать члены не влияют на действительность ссылок элементов контейнера, но могут привести к аннулированию всех итераторов контейнера. Элементы стирания недействительны только итераторам и ссылки на стертые элементы и сохраняют относительный порядок элементов, которые не стираются.
Если моя интерпретация записки от cppreference.com правильно и выше контура зависит от неопределенного поведения в C++ 11, что является самым эффективным способом решения этой проблемы в C++ 11?
Обычно, когда ограничение усиливается так, это потому, что все составители, представленные членами комитета, уже в соответствии. Вы правы, чтобы нервничать. –
@MarkRansom Есть ли способ быть в безопасности? I.e., каков правильный способ сделать это в стандарте C++ 11? – foxcub
Я подозреваю, что * не был * способ гарантировать безопасность, таким образом, изменение стандарта. –