Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Аналог метода extract для std::set/std::map, когда исходный контейнер больше не потребуется #582

Open
prigluchenie opened this issue Nov 15, 2023 · 2 comments

Comments

@prigluchenie
Copy link

prigluchenie commented Nov 15, 2023

Проблема
Для переноса узла 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, и с аналогичным функтором для передачи владения узлами.

@GitSparTV
Copy link

А может merge с перегрузкой для rvalue?

@prigluchenie
Copy link
Author

prigluchenie commented Nov 15, 2023

А может merge с перегрузкой для rvalue?

Это решает лишь частный случай, когда

  • нужно перенести узлы в единственную мапу, а не раскладывать по разным
  • не позволяет отбросить отдельные узлы по условию
  • не позволяет увидеть узел с правом inplace-модификации ключа

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants