зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1700498 - nsTSetInserter::operator* returns a proxy - r=sg
Previously `operator*` returned the iterator, and the templated `operator=` would handle the value insertion. However that `operator=` prevented a defaulted copy-assignment operator, which is used in some algorithms to overwrite the iterator itself. So now `operator*` returns a proxy, which implements the templated `operator=` that is used to insert a value. This allows the nsTSetInserter to have a its defaulted `operator=`. Side-effect: `E` (the hash's KeyClass) is not needed anymore in nsTSetInserter, so it's only templated on the set type. Tech note: `std::back_insert_iterator` doesn't use a value, but has explicitly-defined `operator=(const typename Container::value_type&)` and `operator=(typename Container::value_type&&)`. Unfortunately, some of our stored value types are references (e.g.: `nsStringHashKey::KeyType` is `const nsAString&`), which, due to reference collapsing, would have made both `operator=`'s have the same signature! That's why this implementation uses a proxy sub-type with a single templated `operator=` that can handle anything. Differential Revision: https://phabricator.services.mozilla.com/D109587
This commit is contained in:
Родитель
0c7e8b4d04
Коммит
2400d86309
|
@ -152,22 +152,28 @@ inline void ImplCycleCollectionTraverse(
|
|||
}
|
||||
|
||||
namespace mozilla {
|
||||
template <typename E, typename SetT>
|
||||
template <typename SetT>
|
||||
class nsTSetInserter {
|
||||
SetT* mSet;
|
||||
|
||||
class Proxy {
|
||||
SetT& mSet;
|
||||
|
||||
public:
|
||||
explicit Proxy(SetT& aSet) : mSet{aSet} {}
|
||||
|
||||
template <typename E2>
|
||||
void operator=(E2&& aValue) {
|
||||
mSet.Insert(std::forward<E2>(aValue));
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
using iterator_category = std::output_iterator_tag;
|
||||
|
||||
explicit nsTSetInserter(SetT& aSet) : mSet{&aSet} {}
|
||||
|
||||
template <typename E2>
|
||||
nsTSetInserter& operator=(E2&& aValue) {
|
||||
mSet->Insert(std::forward<E2>(aValue));
|
||||
return *this;
|
||||
}
|
||||
|
||||
nsTSetInserter& operator*() { return *this; }
|
||||
Proxy operator*() { return Proxy(*mSet); }
|
||||
|
||||
nsTSetInserter& operator++() { return *this; }
|
||||
nsTSetInserter& operator++(int) { return *this; }
|
||||
|
@ -176,7 +182,7 @@ class nsTSetInserter {
|
|||
|
||||
template <typename E>
|
||||
auto MakeInserter(nsTBaseHashSet<E>& aSet) {
|
||||
return mozilla::nsTSetInserter<E, nsTBaseHashSet<E>>{aSet};
|
||||
return mozilla::nsTSetInserter<nsTBaseHashSet<E>>{aSet};
|
||||
}
|
||||
|
||||
#endif // XPCOM_DS_NSTHASHSET_H_
|
||||
|
|
Загрузка…
Ссылка в новой задаче