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)