The reason they're only overriding < is because by default that's what ordered containers use to compare values, so that's all they need to define to answer the question.
#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 }
No, the other operators are not implicitly defined in terms of it (nor in terms of anything else). In a real application, if you've defined one you should define them all.
Alternatively, if < doesn't make sense for your type syntactically, but ordering them is still valuable, define a usable default predicate that users should pass to the ordered container's predicate template argument.
#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() is the function call operator. It allows your object to be "called":
struct foo { void operator()(int x) { std::cout << x << std::endl; } }; foo f; f(5); // calls foo::operator()(5)
operator()allows for sorting by other criteria than an object's defaultoperator<method. For example, a shelf of books can be ordered by title, author or Dewey Decimal number. A book class can't have 3 defaultoperator<functions. So a function is written to compare two books by author or another function written to compare by Dewey Decimal system.operator()is. Separate, they are both probably very searchable.std::rel_ops.