// stroustrup way
friend bool operator== (MyClass &lhs, MyClass &rhs);
Arguments should be const
:
friend bool operator==(const MyClass& lhs, const MyClass& rhs);
This is preferred as it works when the first argument can be implicitly constructed. For example, if std::string
only had a member function operator==
, then "abc" == my_std_string
would not invoke it! But, the non-member function can be invoked by implicitly constructing a string from "abc" (better yet in this particular case, a separate bool operator==(const char*, const std::string&)
can be provided for performance reasons, but the point still stands - non-member functions can help ensure the operator works with the user-defined-type on either side).
Separately, implicit constructors are a bit dangerous - and you want to think hard about the convenience versus danger of using them.
Similarly, if you had ObjectOfAnotherClassType == ObjectOfMyClassType
, and AnotherClass
sported a casting operator such as operator MyClass() const
, then the non-member/friend operator==
would allow the cast to kick in and be able to do the comparison; the member operator==
form would not.
A final point: you only need to make the non-member operator==
a friend
if there's no other way to access the data you need to compare. Otherwise, you can declare/define it outside the class, optionally inline
if you want the implementation in a header that may be included from multiple translation units eventually linked into the same executable. Not much harm though, and making it a friend
is the only way to put the definition inside a class template, where you don't have to repeat the "template <typename ...>
" stuff and parameters....