Ответ 1
Третий аргумент называется predicate. Вы можете представить предикат как функцию, которая принимает несколько аргументов и возвращает true
или false
.
Так, например, вот предикат, который говорит вам, является ли целое число нечетным:
bool isOdd(int n) {
return n & 1;
}
Вышеприведенная функция принимает один аргумент, поэтому вы можете назвать его unary предикат. Если вместо этого потребовалось два аргумента, вы бы назвали его предикатом binary. Вот двоичный предикат, который говорит вам, если его первый аргумент больше второго:
bool isFirstGreater(int x, int y) {
return x > y;
}
Предикаты обычно используются очень универсальными функциями, позволяющими вызывающей функции определять, как должна себя вести функция, написав свой собственный код (при использовании таким образом предикат является специализированной формой callback). Например, рассмотрим функцию 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>
- это двоичный предикат, который сообщает, что его первый аргумент больше второго. Это также шаблонный struct
, что означает, что он имеет много разных форм, основанных на типе его аргументов. Этот тип необходимо указать, поэтому greater<int>
- это специализированная специализация по типу int
(читайте больше на шаблонах С++, если вы считаете нужным).
Итак, если 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, которые почти одинаковы в С++), которые вызываются, называются объектами функций или функторы.