Почему в стандартной библиотеке есть find и find_if?

Не может ли find_if быть просто перегрузкой find ? Вот как std :: binary_search и друзья делают это ...

11
задан GManNickG 21 August 2010 в 04:49
поделиться

4 ответа

Предикат является допустимой вещью для поиска, так что вы можете прийти к двусмысленности.


Представьте, что find_if переименовывается в find, тогда у вас есть:

template <typename InputIterator, typename T>
InputIterator find(InputIterator first, InputIterator last, const T& value);

template <typename InputIterator, typename Predicate>
InputIterator find(InputIterator first, InputIterator last, Predicate pred);

Что же делать с:

find(c.begin(), c.end(), x); // am I finding x, or using x to find?

Вместо того, чтобы пытаться придумать какое-то запутанное решение чтобы дифференцировать по x (что не всегда возможно*), проще просто разделить их.

*Это было бы двусмысленно, независимо от того, какова ваша схема или насколько мощной она может быть†:

struct foo
{
    template <typename T>
    bool operator()(const T&);
};

bool operator==(const foo&, const foo&);

std::vector<foo> v = /* ... */;
foo f = /* ... */; 

// f can be used both as a value and as a predicate
find(v.begin(), v.end(), f); 

†Сохраняйте чтение мыслей.

16
ответ дан 3 December 2019 в 06:44
поделиться

Вот что сказал Страуструп (Язык программирования C ++, 18.5.2):

Если find () и find_if () имели то же имя, удивительные возможности привел бы. В целом _if суффикс используется для обозначения того, что алгоритм принимает предикат.

Относительно того, что именно представляет собой эта «двусмысленность», Стив Джессоп ответил, что в своем (с самым высоким рейтингом) ответе на этот вопрос SO .

(примечание: этот вопрос фактически может квалифицироваться как тот же вопрос, что и этот. Я недостаточно умен в C ++ arcania, чтобы решить).

3
ответ дан 3 December 2019 в 06:44
поделиться

У него не может быть того же имени, потому что это может привести к двусмысленности. Предположим, что у нас есть перегрузка find вместо find_if . Затем предположим:

// Pseudo-code
struct finder
{
    bool operator()(const T&) const { ... }
    bool operator==(const finder& right) const { ... }
}

std::vector<finder> finders;

finder my_finder;

std::find(finders.begin(), finders.end(), my_finder);

У находки не будет способа устранить несоответствие: если она попытается найти искатель в контейнере, или используйте Finder , чтобы выполнить операцию поиска? Чтобы решить эту проблему, они создали два имени функции.

1
ответ дан 3 December 2019 в 06:44
поделиться

Конечно, вы можете реализовать find в терминах find_if , используя своего рода предикат равенства.

Я предполагаю, что настоящая причина в том, что вы можете довольно легко реализовать find и предоставить высокопроизводительные специализированные реализации для типичных встречающихся типов; если вы используете find_if , предикат, который вы передаете, может быть произвольно сложным, что дает разработчику библиотеки меньше возможностей для оптимизации.

Кроме того, в C ++ существует философия «вы не платите за то, что не используете», и вы обычно ожидаете, что не захотите платить за оценку предиката, если простое сравнение подойдет.

-2
ответ дан 3 December 2019 в 06:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: