What operators should be declared as friends?
This really depends on whether a class is going to be on the left- or right-hand side of the call to operator==
(or other operator). If a class is going to be on the right-hand side of the expression—and does not provide an implicit conversion to a type that can be compared with the left-hand side—you need to implement operator==
as a separate function or as a friend
of the class. If the operator needs to access private class data, it must be declared as a friend
.
For example,
class Message {
std::string content;
public:
Message(const std::string& str);
bool operator==(const std::string& rhs) const;
};
allows you to compare a message to a string
Message message("Test");
std::string msg("Test");
if (message == msg) {
// do stuff...
}
but not the other way around
if (msg == message) { // this won't compile
You need to declare a friend operator==
inside the class
class Message {
std::string content;
public:
Message(const std::string& str);
bool operator==(const std::string& rhs) const;
friend bool operator==(const std::string& lhs, const Message& rhs);
};
or declare an implicit conversion operator to the appropriate type
class Message {
std::string content;
public:
Message(const std::string& str);
bool operator==(const std::string& rhs) const;
operator std::string() const;
};
or declare a separate function, which doesn't need to be a friend if it doesn't access private class data
bool operator==(const std::string& lhs, const Message& rhs);
When you have your operators outside the class, both parameters can participate in implicit type conversions (whereas with operators being defined in the class body, only the right-hand operands can). Generally, that's a benefit for all the classic binary operators (i.e. ==
,!=
, +
, -
, <<
, ... ).
Of course you should only declare operators friend
s of your class if you need to and not if they compute their result solely based on public members of the class.