I never understood that argument. Even in C operators do different things depending on what types you pass it. Two very simple examples:
1. Adding a number to a char* vs adding a number to an int* (or a pointer to any other larger type). The second automatically creates an invisible multiplication. This was confusing for me when I first learned C after already knowing the concept of a memory address (which is just a number). It was an unexpected abstraction for me.
2. This regularly bites novices to programming: Dividing two numbers. If at least one of them is floating point, you get the 'correct' result, overwise rounded towards zero. To 'fix' it, you have to explicitly cast at least one of them to float or double. Then the language imlpicitly casts the other for you. std::pow went the other way, which is less confusing. It always promotes integers to floating point numbers and returns a floating point result.
As soon as your language has types and operators, you get operators that do different things based on the types of the values they are applied to. The only new thing that operator overloading adds is that it makes libraries first class citizens.