Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why C++ operator overloading requires "having at least one parameter of class type"?

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 type.

For example, string("hello")+"world" compiles "hello"+"world" doesn't. And when I want to overload the + on two C strings.

std::string operator+ (const char* s1, const char* s2)

I get the following error.

error: ‘std::string operator+(const char*, const char*)’ must have an argument of class or enumerated type

I have two questions.

  1. Is this restriction part of the language specification? If yes, why C++ designers want to do that?

  2. std::string has constructor like string (const char* s);, which implies that compiler can do implicit class-type conversion from char* to string. When we call "hello"+"world", why doesn't the compiler convert the two char* "s to two strings? After all, there is a overloading "+" on two std::strings. string operator+ (const string& lhs, const string& rhs);

like image 469
Peng Zhang Avatar asked May 06 '14 22:05

Peng Zhang


2 Answers

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.

like image 183
peppe Avatar answered Sep 27 '22 23:09

peppe


  1. 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.

  1. "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...).

like image 45
rodrigo Avatar answered Sep 27 '22 22:09

rodrigo