Why can some operators only be overloaded as member functions, other as non-member "free" functions and the rest of them as both?
What is the rationale behind those?
How to remember which operators can be overloaded as what (member, free, or both)?
The question lists three classes of operators. Putting them together on a list helps, I think, with understanding why a few operators are restricted in where they can be overloaded:
Operators which have to be overloaded as members. These are fairly few:
operator=()
. Allowing non-member assignments seems to open the door for operators hijacking assignments, e.g., by overloading for different versions of const
qualifications. Given that assignment operators are rather fundamental that seems to be undesirable.operator()()
. The function call and overloading rules are sufficiently complicated as is. It seems ill-advised to complicate the rules further by allowing non-member function call operators.operator[]()
. Using interesting index types it seems that could interfere with accesses to operators. Although there is little danger of hijacking overloads, there doesn't seem to be much gain but interesting potential to write highly non-obvious code.operator->()
. Off-hand I can't see any bad abuse of overloading this operator a non-member. On the other hand, I also can't see any. Also, the class member access operator has rather special rules and playing with potential overloads interfering with these seems an unnecessary complication.Although it is conceivable to overload each of these members are a non-member (especially the subscript operator which is works on arrays/pointers and these can be on either side of the call) it seems surprising if, e.g., an assignment could be hijacked by a non-member overload which which is a better match than one of the member assignments. These operators are also rather asymmetric: you generally wouldn't want to support conversion on both sides of an expression involving these operators.
That said, e.g., for a lambda expression library it would be nice if it were possible to overload all of these operators and I don't think there is an inherent technical reason to preventing these operators from being overloadable.
Operators which have to be overloaded as non-member functions.
operator"" name()
This operator is somewhat of an odd-ball and, arguably not really really an operator. In any case, there is no object to call this member on for which members could be defined: the left argument of user-defined literals are always built-in types.
Not mentioned in the question but there are also operator which can't be overloaded at all:
.
.*
::
?:
These four operators were considered to be too fundamental to be meddled with at all. Although there was a proposal to allow overloading operator.()
at some point there isn't strong support doing so (the main use case would be smart references). Although there are certainly some contexts imaginable where it would be nice to overload these operators, too.
Operators which can be overloaded either as members or as non-members. This is the bulk of the operators:
operator++()
, operator--()
, operator++(int)
, operator--(int)
operator*()
operator&()
operator+()
, operator-()
operator!()
(or operator not()
)operator~()
(or operator compl()
)operator==()
, operator!=()
, operator<()
, operator>()
, operator<=()
, and operator>()
operator+()
, operator-()
, operator*()
, operator/()
, operator%()
operator&()
(or operator bitand()
), operator|()
(or operator bit_or()
), operator^()
(or operator xor()
)operator<<()
and operator>>()
operator||()
(or operator or()
) and operator&&()
(or operator and()
)operator@=()
(for @
being a suitable operator symbol()operator,()
(for which overloading actually kills the sequence property!)operator->*()
operator new()
, operator new[]()
, operator new[]()
, and operator delete[]()
The operators which can be overloaded either as members or as non-members are not as necessary for fundamental object maintenance as the other operators. That is not to say that they are not important. In fact, this list contains a few operators where it is rather questionable whether they should be overloadable (e. g., the address-of operator&()
or the operators which normally cause sequencing, i. e., operator,()
, operator||()
, and operator&&()
.
Of course, the C++ standard doesn't give a rationale on why things are done the way they are done (and there are also no records of the early days when these decisions where made). The best rationale can probably be found in "Design and Evolution of C++" by Bjarne Stroustrup. I recall that the operators were discussed there but there doesn't seem to be an electronic version available.
Overall, I don't think there are really strong reasons for the restrictions other than potential complication which was mostly not considered worth the effort. I would, however, doubt that the restrictions are likely to be lifted as the interactions with existing software are bound to change the meaning of some program in unpredictable ways.