J'essaie de mettre en œuvre ce système de remplacement ou de fusion.
template<typename T>
T& EmplaceOrMerge(std::unordered_set<T>& s,
T&& t,
std::function<void(T&& a, T& b)> merge)
{
auto it = s.emplace(std::move(t));
T& u = const_cast<T&>(*it.first);
if (!it.second)
merge(std::move(t), u);
return u;
}
La fonction de fusion modifie son deuxième argument de manière à préserver sa valeur hachée. Je m'intéresse à l'utilisation de la fonction std::move(t)
dans le cas de la fusion, car le emplace
l'a peut-être déjà déplacé. J'ai lu la mise en œuvre par Microsoft de unordered_set
et il existe un cas particulier très intéressant, if constexpr (_In_place_key_extractor::_Extractable)
. Elle reconnaît que son argument std::move(t)
peut être hachée directement (et comparée à operator==
directement), sans construire un autre objet T
et renvoie immédiatement la valeur équivalente dans le unordered_set
quand il y en a un.
Ce cas particulier se produit-il dans toutes les implémentations de la bibliothèque standard ? Si ce n'est pas le cas, j'ai un comportement non défini, et je me demande s'il y a une autre façon de coder cela. EmplaceOrMerge
.