Почему в стандартной библиотеке есть find и find_if? - PullRequest
10 голосов
/ 20 августа 2010

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

Ответы [ 4 ]

15 голосов
/ 20 августа 2010

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


Рассмотрим 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); 

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

3 голосов
/ 20 августа 2010

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

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

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

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

1 голос
/ 20 августа 2010

У него не может быть того же имени, потому что будет двусмысленность. Предположим, что у нас была перегрузка 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);

find не сможет устранить несоответствие: попытаться найти finder в контейнере или использовать finder для выполнения операции поиска? Чтобы решить эту проблему, они создали два имени функции.

0 голосов
/ 20 августа 2010

Вы, безусловно, можете реализовать find в терминах find_if, используя какой-то предикат равенства.

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

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

...