Это сложный случай. erase
имеет перегрузку, которая принимает параметр const key_type&
, поэтому мы можем попытаться создать "устаревший" unique_ptr
, чтобы получить значение ha sh удаляемого элемента:
template <typename T>
auto erase(std::unordered_set<std::unique_ptr<T>>& set, T* ptr)
{
std::unique_ptr<T> stale_ptr{ptr};
auto ret = set.erase(stale_ptr);
stale_ptr.release();
return ret;
}
( live demo )
Эта версия, однако, в целом не является безопасной для исключения, поскольку release
не будет вызываться, если set.erase
выдает исключение. В этом случае это не проблема, поскольку std::equal_to<std::unique_ptr<T>>::operator()
никогда не вызывает исключение. В общем случае мы можем злоупотреблять unique_ptr
(!) Для обеспечения безопасности исключений, гарантируя, что release
вызывается независимо от того, завершается ли функция нормально или исключительно:
template <typename T>
auto erase(std::unordered_set<std::unique_ptr<T>>& set, T* ptr)
{
std::unique_ptr<T> stale_ptr{ptr};
auto release = [](std::unique_ptr<T>* p) { p->release(); };
std::unique_ptr<std::unique_ptr<T>, decltype(release)> release_helper{&stale_ptr, release};
return set.erase(stale_ptr);
}
( живое демо )