Его не хватает, потому что его никто не добавил. Никто не добавил его, потому что контейнеры из STL, std
включенные в библиотеку, были разработаны с минимальным интерфейсом. (Обратите внимание, что std::string
это не произошло из STL таким же образом).
Если вас не беспокоит какой-то странный синтаксис, вы можете подделать его:
template<class K>
struct contains_t {
K&& k;
template<class C>
friend bool operator->*( C&& c, contains_t&& ) {
auto range = std::forward<C>(c).equal_range(std::forward<K>(k));
return range.first != range.second;
// faster than:
// return std::forward<C>(c).count( std::forward<K>(k) ) != 0;
// for multi-meows with lots of duplicates
}
};
template<class K>
containts_t<K> contains( K&& k ) {
return {std::forward<K>(k)};
}
использование:
if (some_set->*contains(some_element)) {
}
По сути, вы можете писать методы расширения для большинства std
типов C ++, используя эту технику.
Имеет смысл просто сделать это:
if (some_set.count(some_element)) {
}
но меня забавляет метод метода расширения.
На самом деле печально то, что написание эффективного contains
может быть быстрее на multimap
или multiset
, поскольку им просто нужно найти один элемент, а count
нужно найти каждый из них и посчитать их .
Мультимножество, содержащее 1 миллиард копий 7 (вы знаете, на случай, если у вас закончатся), может иметь очень медленное .count(7)
, но могло быть очень быстрое contains(7)
.
С помощью вышеупомянутого метода расширения мы могли бы сделать его быстрее в этом случае, используя lower_bound
, сравнивая end
, а затем сравнивая с элементом. Однако выполнение этого как для неупорядоченного, так и для упорядоченного мяуканья потребует необычных перегрузок SFINAE или конкретных контейнеров.