Они совершенно разные алгоритмы: find_if
выглядит линейно для первого элемента, для которых предикат является истинным, binary_search
имеет преимущество, что диапазон сортируется для проверки в логарифмическое время если данное значение в нем.
Предикат для binary_search
определяет функцию, в соответствии с которой диапазон заказан (вы, скорее всего, захотите использовать тот же предикат, который вы использовали для его сортировки).
Вы не можете использовать сортировку для поиска значения, удовлетворяющего некоторому совершенно несвязанному предикату (в любом случае вам придется использовать find_if
). Обратите внимание, однако, что с отсортированным диапазоном вы можете сделать больше, чем просто проверить наличие с lower_bound
, upper_bound
и equal_range
.
вопрос, какова цель std::binary_function
является интересным.
Все, что он делает, это предоставление typedefs для result_type
, first_argument_type
и second_argument_type
. Это позволит пользователям, учитывая функтор в качестве аргумента шаблона, чтобы найти и использовать эти типы, например
template <class T, class BinaryFunction>
void foo(const T& a, const T& b, BinaryFunction f)
{
//declare a variable to store the result of the function call
typename BinaryFunction::result_type result = f(a, b);
//...
}
Однако, я думаю, что единственное место, где они используются в стандартной библиотеке создает другие функторные оберток подобный bind1st
, bind2nd
, not1
, not2
. (Если бы они использовались для других целей, люди будут кричать на вас в любое время, когда вы использовали функцию в качестве функтора, так как это было бы непереносимо.)
Например, binary_negate
может быть реализован как (GCC):
template<typename _Predicate>
class binary_negate
: public binary_function<typename _Predicate::first_argument_type,
typename _Predicate::second_argument_type, bool>
{
protected:
_Predicate _M_pred;
public:
explicit
binary_negate(const _Predicate& __x) : _M_pred(__x) { }
bool
operator()(const typename _Predicate::first_argument_type& __x,
const typename _Predicate::second_argument_type& __y) const
{ return !_M_pred(__x, __y); }
};
конечно, operator()
может, возможно, просто шаблон, и в этом случае эти определения типов были бы не нужны (любые недостатки?). Возможно, есть методы метапрограммирования, чтобы выяснить, какие типы аргументов не требуют, чтобы пользователь явно вводил их явно. Полагаю, что это немного сработает с силой, которую дает C++ 0x, например, когда я хотел бы реализовать отрицатель для функции любой арности с вариативными шаблонами ...
(ИМО C++ 98 функторы немного слишком негибкими и примитивными по сравнению, например, с std::tr1::bind
и std::tr1::mem_fn
, но, вероятно, при поддержке время компиляции для методов метапрограммирования, необходимых, чтобы эти работы были не так хороши, и, возможно, методы все еще были обнаружены.)
Ваше первое предложение сбивает с толку, поскольку предикатная версия 'binary_search' * * завершается в O (log n) времени. Это только предикатная версия с одним аргументом, которую предлагает Pmr, которая не удовлетворяет требованию сложности, а не предикатной версии, которую мы имеем сегодня. –
@Rob: спасибо, отредактируйте. –