Я только что заметил, что std::map и std::set имеют функцию-член equal_range(), возвращающую диапазон значений итератора для определенного ключа. Какой это имеет смысл, если std::map и std::set всегда являются упорядоченными контейнерами «ключ/значение» (как в одном ключе для одного значения или в обоих вместе).
Я бы ожидал, что эта функция-член будет иметь std::multimap и std::multiset, поскольку оба они допускают использование нескольких значений, использующих один и тот же ключ, и, конечно, они оба это делают. Что мне не хватает?
@KarlKnechtel, на мой взгляд, я бы не ожидал, что эта функция будет существовать для карты и установки. Но, как указано в (принятом) ответе, функция полезна для обобщения, даже если на самом деле она не служит цели для отображения и установки.
В C++14 он получил новые функциональные возможности благодаря общему поиску is_transparent: godbolt.org/z/b5nqvKf8o (хотя, очевидно, это не основная причина, по которой он был доступен до C++14)





Это имеет смысл как соответствие другому ассоциативному контейнеру. Точно так же std::map и std::set имеют метод count, хотя они могут возвращать только 0 или 1 и find уже выполняет свою работу. Вы можете использовать count с ассоциативным контейнером независимо от того, может ли он содержать более 1 одного и того же элемента (см. std::multi_map). И вы можете использовать equal_range для std::unordered_map так же, как и для заказанного std::map. Вы правы, что для std:map и std::set они редко бывают полезны, но предположим, что вы пишете общий код, который принимает ассоциативный контейнер (упорядоченный или нет):
template <typename T,typename E>
void foo(T& t,E e) {
auto p = t.equal_range(e);
//...
}
Не существует формального требования, чтобы все ассоциативные контейнеры имели equal_range, но начиная с C++20 вы можете написать концепцию, требующую T must have equal_range, и использовать шаблон foo также с std::map.
Я так и думал, но хорошо, что это подтвердилось. Возможно, о таких функциях-членах следует упомянуть на сайте cppreference.com.
@marcbf сложно заметить разницу. Некоторые предпочитают использовать std::map::count, хотя считать нечего. Они считают это более удобным, чем std::map::find() != std::map::end(). Насколько я знаю, мне ничего не известно, но могут быть аналогичные варианты использования методов, которые вы считаете «бесполезными», например std::map::equal_range
Тем не менее @marcbf, имейте в виду, что комитет C++ зашел так далеко - они не предоставляют «один и тот же» API для каждого контейнера и по-прежнему основывают его на том, что может делать базовая реализация (обычно они имеют представление о том, что они ожидают, что это произойдет, и строят свои определения исходя из этого). Таким образом, вы можете спросить set, сколько элементов x он содержит, даже если единственный возможный ответ — 0 или 1, но вы не можете спросить vector об этом. Поиск элемента — это «естественная» операция над множеством, для которой он был разработан, но она неэффективна для вектора, поэтому вектор ее не имеет.
«Как это имеет смысл, когда карта и набор всегда представляют собой упорядоченные контейнеры ключ/значение (как в одном ключе для одного значения или в обоих вместе) контейнерах». Я не понимаю. Как вы думаете, что
equal_rangeдолжно вернуться вместо этого и почему? Что еще более важно, почему цитируемый факт должен влиять на результатequal_range?