Третий аргумент называется предикатом .Вы можете думать о предикате как о функции, которая принимает несколько аргументов и возвращает true
или false
.
Так, например, вот предикат, который говорит вам, является лицелое число нечетное:
bool isOdd(int n) {
return n & 1;
}
Приведенная выше функция принимает один аргумент, так что вы можете назвать ее унарный предикат.Если бы вместо этого потребовалось два аргумента, вы бы назвали его предикатом двоичный .Вот двоичный предикат, который сообщает вам, если его первый аргумент больше, чем второй:
bool isFirstGreater(int x, int y) {
return x > y;
}
Предикаты обычно используются функциями очень общего назначения, чтобы вызывающая функция могла указать, как функция должнавести себя путем написания собственного кода (при использовании таким образом предикат является специализированной формой callback ).Например, рассмотрим функцию sort
, когда она должна отсортировать список целых чисел.Что если бы мы захотели отсортировать все нечетные числа перед всеми четными?Мы не хотим, чтобы нас заставляли писать новую функцию сортировки каждый раз, когда мы хотим изменить порядок сортировки, потому что механика (алгоритм) сортировки явно не связана со спецификой (в каком порядке мы хотим это сделать).sort).
Итак, давайте дадим sort
наш собственный предикат, чтобы сделать его сортировку в обратном порядке:
// As per the documentation of sort, this needs to return true
// if x "goes before" y. So it ends up sorting in reverse.
bool isLarger(int x, int y) {
return x > y;
}
Теперь это будет сортировать в обратном порядке:
sort(data, data+count, isLarger);
Способ, которым это работает, заключается в том, что sort
внутренне сравнивает пары целых чисел, чтобы решить, какой из них должен идти перед другим.Для такой пары x
и y
она делает это, вызывая isLarger(x, y)
.
Итак, на данный момент вы знаете, что такое предикат, где вы можете его использовать и как создать свой собственный,Но что означает greater<int>
?
greater<T>
- это двоичный предикат, который сообщает, больше ли его первый аргумент, чем второй.Это также templated struct
, что означает, что он имеет много различных форм в зависимости от типа его аргументов.Этот тип должен быть указан, поэтому greater<int>
- это специализация шаблона для типа int
(читайте больше о шаблонах C ++, если вы чувствуете необходимость).
Так что если greater<T>
такое struct
, как это тоже может быть предикатом?Разве мы не говорили, что предикаты являются функциями ?
Ну, greater<T>
- это функция в том смысле, что она может вызываться : она определяет оператор bool operator()(const T& x, const T& y) const;
, что делает написание этого допустимого:
std::greater<int> predicate;
bool isGreater = predicate(1, 2); // isGreater == false
Объекты типа класса (или struct
s, что почти одинаково в C ++), которые можно вызывать, называются функциональными объектами или функторы .