The chapter 14.1 of \"C++ primer 5th edition\" reads,
An operator function must either be a member of a class or have at least one parameter of class typ
Is this restriction part of the language specification? If yes, why C++ designers want to do that?
Yes, it is. Quoting from N3337, §13.5.6 [over.oper]:
An operator function shall either be a non-static member function or be a non-member function and have at least one parameter whose type is a class, a reference to a class, an enumeration, or a reference to an enumeration.
About the "why" part, because removing this requirement would mean that you could overload operators for builtin types, which already have their operator semantics defined. That's something totally undesiderable.
For instance, do you think that defining this makes any sense?
int operator+(int a, int b) { return a - b; }
Does it allow more people to reason about your program when they read your code, or is it just something surprising that effectively breaks your reasoning?
What happens if we get pointers into the game?
bool operator==(const char *str1, const char *str2) {
return strcmp(str1, str2) == 0;
}
Would you expect that operator==
now dereferences memory? I wouldn't. It's surprising. It goes against what the Standard already says about these operators. It breaks what every C program in the last 25 years behaved like. The language shouldn't let you do this kind of abuses.
- Is this restriction part of the language specification?
Yes, it is. Why? Well, the main reason is probably because redefining the usual operators for standard types is seen as obfuscating. Imagin overloading operator+(int,int)
or operator+(int,char*)
. That would change the meaning of existing code!
You could argue that there are operators between standard types that are not defined, so you could safely override them, for example operator*(char*,int)
, but that is usually seen as rather useless.
Moreover, operator overloads must be global, (or be in the namespace of some of its members (argument dependent lookup), but with standard types there are no namespace to depend on), so interoperatibility between libraries that fancy to override them would be a nightmare.
"hello" + "world"
: why doesn't the compiler convert the two char* "s to two strings?
Well, for one, std::operator+(const std::string&, const std::string&)
is in namespace std;
so it will not be found by default.
You could try calling the operator explicitly: std::operator+("hello", "world")
, but alas, there are so many operator+()
overloads, many of them templates, that the call is ambiguous.
So, taking all this into account, I think that a reasonable requirement is that at least one of the operators to be of a user-defined type. Think about it: the global and namespace problem is solved, ADL can be used (actually it was invented for this use) and it is impossible to redefine an operator with an existing meaning (except operator,()
and operator&()
, I think, but who wants to override these...).
As Bjarne said in Design and Evolution, the goal was to make it easy to extend the language, not to mutate it. If you allowed overloading only builtin types, you would change the language, and allowing that went against the design goals. (For example, it would encourage the formation of mutually incompatible dialects and fracture the community.)