Я'м сильно с помощью СТД::набор И Л;int> и я часто просто должны проверить, если такой набор содержит число или нет.
Я'д найти его естественно писать:
if (myset.contains(number))
...
Но из-за отсутствия члена содержит
, мне нужно написать громоздкой:
if (myset.find(number) != myset.end())
..
или не так очевидна:
if (myset.count(element) > 0)
..
Есть причина для этого дизайнерского решения ?
Я думаю, что это было вероятно, потому, что они пытались сделать с std::setи
СТД::мультимножествокак можно более похожими. (И, очевидно, "количество" имеет вполне разумный смысл для СТД::мультимножество
.)
Лично я думаю, что это было ошибкой.
Это не'т выглядеть совсем уж плохо, если вы делаете вид, что "количество" - это просто неправильное написание "содержит" и написать тест, как:
if (myset.count(element))
...
Это's все еще позор, хотя.
Уметь писать если (S.содержит())
, содержится () должен возвращать
буль(или типа кабриолет
буль`, но это уже другая история), как binary_search не будет.
В Основная причина за дизайнерское решение ** не сделать это таким образом, что содержит (), который возвращает
буль` бы потерять ценную информацию о том, где элемент находится в коллекции**. найти () сохраняет и возвращает эту информацию в виде итератора, поэтому это лучший выбор для универсальной библиотеки как STL. Это всегда была руководящим принципом для Алексей Степанов, как он часто объяснял (например, [здесь][1]).
Как на граф () подхода в целом, хотя это'ы часто так временное решение, проблема в том, что он делает больше работы, чем содержится()
бы не.
Это не означает, что типа bool содержит()
это't очень желательны или даже необходимы. Некоторое время назад у нас была долгая дискуссия][2] об этой же проблеме в
Стандарт ISO на C++ - будущее группы предложений.
[2]: https://groups.google.com/a/isocpp.org/forum/#!searchin/std-proposals/leo 20heinsaar$/std-proposals/onDKXlivhhk
Ей не хватает его, потому что никто не добавил его. Никто не добавил, он ведь контейнеры из STL в том, что библиотека СТД
зарегистрирована, где разработан, чтобы быть минимальным в интерфейс. (Обратите внимание, что СТД::строка` не выходила из стл таким же образом).
Если вы Don'т ум какие-то странные синтаксис, вы можете поддельные его:
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
и видах, используя эту технику.
Это делает намного больше смысла, чтобы просто сделать это:
if (some_set.count(some_element)) {
}
но меня позабавил метод метод расширения.
Действительно печально, что написание эффективного "содержит" может быть быстрее на Мультикарты
или `мультимножество, а они просто должны найти один элемент, в то время как "количество", чтобы найти каждого из них и считать их.
Мультимножество, содержащее 1 млрд экземпляров 7 (знаешь, на случай, если закончатся) может быть очень медленно.графа(7), но может иметь очень быстрый содержит(7)
.
С выше метод расширения, мы могли бы сделать это быстрее, в этом случае с помощью lower_boundв сравнении с
конца`, а затем в сравнении с элементом. Делаешь, что для неупорядоченного мяу, а также упорядоченный мяу понадобятся необычные SFINAE или контейнеров перегрузок.
Вы ищете в конкретном случае и не увидев более широкую картину. Как указано в документации СТД::набор соответствует требованиям [AssociativeContainer][2] концепция. Для этого понятия не имеет никакого смысла, чтобы иметь способ "содержит", так как это в значительной степени бесполезными для СТД::мультимножество " и " с std::multimap, В
, а количество
работает для всех из них. Хотя метод "содержит" может быть добавлен в качестве псевдонима для количество
за СТД::набор
, СТД::МАП
и их хешированной версии (например, длина для размер()в
СТД::строка` ), но похоже, что библиотека создатели не вижу реальной необходимости в этом.
Хотя я не'т знаю, почему СТД::набор
нет содержит
а количество
, который только когда-либо возвращает значение 0
или 1
,
вы можете написать шаблонный "содержит" вспомогательную функцию такой:
template<class Container, class T>
auto contains(const Container& v, const T& x)
-> decltype(v.find(x) != v.end())
{
return v.find(x) != v.end();
}
И использовать его как это:
if (contains(myset, element)) ...
Истинная причина "набора" - это загадка для меня, но одно из возможных объяснений такой же конструкции в "карте" может быть, чтобы помешать людям писать неэффективный код случайно:
if (myMap.contains("Meaning of universe"))
{
myMap["Meaning of universe"] = 42;
}
Что приведет к двум "карта" просмотра.
Вместо этого, вы будете вынуждены получить итератор. Это дает вам психического намек на то, что вы должны использовать итератор:
auto position = myMap.find("Meaning of universe");
if (position != myMap.cend())
{
position->second = 42;
}
которая потребляет только одна "карта" просмотра.
Когда мы осознаем, что set
и карта
сделаны из той же плоти, мы можем применить этот принцип к "набор". То есть, если мы хотим выступать на пункт в "набор", только если она присутствует в "набор", эта конструкция может предотвратить нас от написания кода, как это:
struct Dog
{
std::string name;
void bark();
}
operator <(Dog left, Dog right)
{
return left.name < right.name;
}
std::set<Dog> dogs;
...
if (dogs.contain("Husky"))
{
dogs.find("Husky")->bark();
}
Конечно, все это только домыслы.
Насчет binary_search ?
set <int> set1;
set1.insert(10);
set1.insert(40);
set1.insert(30);
if(std::binary_search(set1.begin(),set1.end(),30))
bool found=true;
Другая причина заключается в том, что это дало бы программист ложное впечатление, что СТД::набор-это набор в математические теории множеств смысла. Если они реализуют это, то многие другие вопросы будут следовать: если СТД::набор содержит() для значения, почему'т он его для другого набора? Где союз(), пересечения() и другие операции над множествами и предикатами?
Ответ, конечно, что некоторые операции уже реализованы в виде функций в <алгоритм> (с std::set_union() и т. д.) и другие так же тривиально реализуется как содержится(). Функции и объекты функций лучше работать с математическими абстракциями, чем члены объекта, и они не ограничиваются конкретным типом контейнера.
Если необходимо реализовать полный математика-набор функциональных возможностей, он имеет не только выбор основного контейнера, но и у него есть выбор из деталей реализации, например, его theory_union() функции работы с неизменяемыми объектами, лучше всего подходит для функционального программирования, или модифицировать операнды и сохранить память? Это было бы реализовано как функция объекта от начала или это'd быть лучше, чтобы реализовать это в C-функции, и использовать std::функция<> если это необходимо?
Как сейчас, СТД::набор-это просто контейнер, хорошо подходит для реализации поставленных в математическом смысле, но это почти так же далеки от теоретической установить как std::вектор из теоретической вектор.