2013-06-26 3 views
1

Я часто вижу, что люди только переопределяют оператора <, а не> или ==. Означает ли это, что по умолчанию оператор> и оператор == реализуются с использованием оператора <?Операторы сравнения C++

Я также часто вижу людей, пишущих (см here)

bool operator() (Node const& n1, Node const& n2) const 
{ 
    // TODO: your condition 
    return n1.a < n2.a; 
} 

Что оператор() означает, здесь тогда? это кажется очень противоречивым.

+0

'operator()' позволяет сортировать по другим критериям, чем метод 'operator <' объекта по умолчанию. Например, полку книг можно заказать по названию, автору или десятичному числу Дьюи. Класс book не может иметь 3 '' '' '' функции '' функции. Таким образом, функция записывается для сравнения двух книг автора или другой функции, написанной для сравнения с системой Dewey Decimal. –

+2

В будущем, пожалуйста, не задавайте сразу два вопроса. Либо спросите, не определены ли операторы в терминах друг друга, либо спросите, что такое 'operator()'. Отдельные, они, вероятно, очень доступны для поиска. – GManNickG

+0

В дополнение к уже указанным ответам найдите 'std :: rel_ops'. –

ответ

3

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

#include <set> 

struct my_fancy_integer 
{ 
    int fancy; 
}; 

// This is all std::set (or any ordered container) needs by default, 
// So for an example answer I won't do anything else (as I expect you to 
// learn and understand *why* it needs this by default). 
bool operator<(const my_fancy_integer& first, const my_fancy_integer& second) 
{ 
    return first.fancy < second.fancy; 
} 

// But I should really also defined the other comparison operators... 
// For example, without operator> defined this would fail: 
// 
// std::set<my_fancy_integer, std::greater<my_fancy_integer>> x; 
// 
// But since you read documentation for std::set and std::greater you 
// understand why this fails: std::set will use std::greater to order 
// the values, and std::greater (by default) will try to use operator>. 

int main() 
{ 
    std::set<my_fancy_integer> x; // okay 
} 

Нет, другие операторы неявно определяются в терминах (ни в терминах чего-либо еще). В реальном приложении, если вы определили один, вы должны определить их все.

В качестве альтернативы, если < не имеет смысла для вашего типа синтаксически, но упорядочение их по-прежнему ценно, определите используемый предикат по умолчанию, который пользователи должны передать аргументу шаблона предиката заданного контейнера.

#include <set> 
#include <string> 
#include <tuple> 

struct my_employee 
{ 
    std::string name; 
    int salary; 
    int yearsEmployed; 
}; 

// Saying one employee is "less" than another doesn't really make sense... 
// But I can still give an *ordering* on them: 
struct my_employee_ordering 
{ 
    bool operator()(const my_employee& first, const my_employee& second) const 
    { 
     // I'll just reuse std::tuple's comparison operator, and tie the 
     // fields of each structure into a tuple to use it. This orders 
     // by name, salary, then yearsEmployed. 
     return std::tie(first.name, first.salary, first.yearsEmployed) < 
       std::tie(second.name, second.salary, second.yearsEmployed); 
    } 
}; 

int main() 
{ 
    // We need to tell std::set how to order employees: 
    std::set<my_employee, my_employee_ordering> x; // okay 
} 

operator() является оператором вызова функции. Это позволяет ваш объект быть «под названием»:

struct foo 
{ 
    void operator()(int x) { std::cout << x << std::endl; } 
}; 

foo f; 
f(5); // calls foo::operator()(5) 
+0

Вы пропустили вторую часть вопроса (я понял, что вопрос был отредактирован) –

+0

@MooingDuck: Edited. Люди действительно не должны сразу задавать два вопроса ... – GManNickG

1

Минимальные сравнения или упорядочения операторов, определенных в < и ==. Другие операторы сравнения могут быть определены в терминах этих:

operator != -- !operator== 
operator >= -- !operator< 
operator <= -- operator== || operator < 
operator > -- !(operator== || operator <) 

boost библиотека содержит шаблоны, которые будут генерировать все остальные операторы. См. «Less_than_comparable» для примера.

Edit 1:
operator() является определяющим операцию заказа, которая зачастую используемые функции сортировки. Например, у вас может быть одна функция, определенная для восходящего упорядочения, и другая функция, определенная для нисходящего упорядочения. Для сортировки вы должны передать либо восходящий функциональный объект, либо нисходящий объект функции.

2

Во-первых, нет. Реализация < неявно определяет == и>. Люди обычно определяют <, потому что стандартная библиотека использует меньше, чем оператор, специально для сравнения сортировки списков и подобных задач.

Оператор() называется оператором вызова функции. В основном, скажем, у меня есть структура Foo следующего

struct foo { 
    int operator()(int a, int b) { 
     return a+b; 
    } 
}; 

Теперь, если у меня есть экземпляр foo называется x, я могу использовать x(6, 5) и он будет вызывать оператор вызова функции с двумя параметрами, которые я дал (6 и 5 в этом случае). Оператор вызова функции предназначен только для обработки структур, подобных функции, и может принимать любые числа и типы параметров или даже не принимать никаких параметров.В примере, который вы указали, когда объект, охватывающий эту функцию, используется как вызов функции, он будет сравнивать объекты двух узлов и возвращает true, если первое меньше второго в соответствии с оператором <.

0

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

Таким образом, вы видите перегрузку «оператора <» для случая, когда функция используется для слабого упорядочения в упорядоченном контейнере, где сравнение не требуется. Класс используется только для этой цели, и поэтому операторы сравнения и т. Д. Не обязательно должны быть реализованы.

оператор() используется для предикатных функторов, чтобы позволить объекту быть «называется» в ясной форме:

struct EqualityPredicate { 
    bool operator()(const Node& lhs, const Node& rhs) const { return lhs == rhs; } 
}; 

EqualityPredicate& equality; 
for (Node hay : haystack) { 
    if(equality(hay, haystack)) 
     doWork(hay); 
} 

Который зовет equality.operator() (сено, стог);

+0

«слабый порядок не требует оператора сравнения». Я думаю, что предложение требует перезаписи. Кроме того, вызов образца такой же, как 'равенство.оператор() ...' не 'равенство-> operator() ...' –

+0

хороший улов, должным образом отредактированный. – kfsone