I want to give hints to std::map::lower_bound.
Why isn't it even allowed?
Suppose we need to implement something like:
static constexpr int TOTAL_SIZE = 1'000'000;
std::map<int, std::string> map{};
for (int i = 0; i < TOTAL_SIZE; ++i) {
map[i] = "some_string" + std::to_string(i);
}
const int key1 = TOTAL_SIZE / 4;
const int key2 = TOTAL_SIZE / 2; /* `key2` is greater than `key1` */
const auto hint = map.lower_bound(key1);
if (hint != map.cbegin() && std::prev(hint)->second != "excluded_string") {
map.insert_or_assign(hint, key1, "first_string_to_insert");
const auto second_hint = map.lower_bound(key2); // we'd rather use `hint` here!
if (second_hint != map.cbegin() && std::prev(second_hint)->second != "other_excluded_string") {
map.insert_or_assign(second_hint, key2, "second_string_to_insert");
}
}
How can we do this logic optimally and without rewriting it completely? The problem is that inability to pass a hint to lower_bound (2nd one) makes us do the same lookup twice. That's 2 times worse performance!
I would be happy, if I could do something like this:
static constexpr int TOTAL_SIZE = 1'000'000;
std::map<int, std::string> map{};
for (int i = 0; i < TOTAL_SIZE; ++i) {
map[i] = "some_string" + std::to_string(i);
}
const int key1 = TOTAL_SIZE / 4;
const int key2 = TOTAL_SIZE / 2; /* `key2` is greater than `key1` */
const auto hint = map.lower_bound(key1);
if (hint != map.cbegin() && std::prev(hint)->second != "excluded_string") {
const auto wanted_hint = map.insert_or_assign(hint, key1, "first_string_to_insert");
const auto second_hint = map.lower_bound(wanted_hint, key2); // like this!
if (second_hint != map.cbegin() && std::prev(second_hint)->second != "other_excluded_string") {
map.insert_or_assign(second_hint, key2, "second_string_to_insert");
}
}
This would allow to run the second lower_bound in amortized O(1) instead of O(log(N)).
Please, share the ideas on how to do that.
And is there a reason std::map::lower_bound does not accept a hint?