Аналог метода extract для std::set/std::map, когда исходный контейнер больше не потребуется
prigluchenie opened this issue · 2 comments
Проблема
Для переноса узла std::set в другой экземпляр контейнера (возможно, с попутной модификацией ключа) есть метод extract, который позволяет переиспользовать аллокацию. Однако частно это требуется сделать для всех элементов контейнера, и исходный контейнер больше не нужен.
Пример, как можно реализовать условную задачу сейчас
std::set<std::string> input{"a", "b", "c"};
std::set<std::string> output_good, output_bad;
while(!input.empty()) {
auto node_handler = input.extract(input.begin());
if (is_good(node_handler.value()) {
node_handler.value() += '!';
output_good.insert(std::move(node_handler));
} else {
output_bad.insert(std::move(node_handler));
}
}
Недостаток этого решения в том, что между итерациями цикла приходится восстанавливать инварианты черно-красного дерева, что избыточно, т.к. объект больше не требуется (в итоге заведомо остается пустой).
Предлагается добавить метод extract_each (условно), который бы позволял максимально эффективно разобрать дерево на отдельные ноды целиком.
Например, код решения исходной задачи с таким методом мог бы выглядеть как-то так
std::move(input).extract_each([&output_good, &output_bad](auto node_handler) {
if (is_good(node_handler.value()) {
node_handler.value() += '!';
output_good.insert(std::move(node_handler));
} else {
output_bad.insert(std::move(node_handler));
}
});
Можно подумать и над вариантом метода extract с дополнительными параметрами диапазона итераторов from, to, и с аналогичным функтором для передачи владения узлами.
А может merge с перегрузкой для rvalue?
А может merge с перегрузкой для rvalue?
Это решает лишь частный случай, когда
- нужно перенести узлы в единственную мапу, а не раскладывать по разным
- не позволяет отбросить отдельные узлы по условию
- не позволяет увидеть узел с правом inplace-модификации ключа