On Monday, 23 June 2025 at 10:14:25 UTC, Jonathan M Davis wrote:
...
Overloaded operators are considered to be part of the type just
like constructors are part of the type, and D has done a number
of things with overloaded operators to try to minimize the
ability to do what many consider to be overloaded operator
abuse (e.g. using using overloaded operators to define a DSL -
or really much of anything that's not trying to behave like the
operators do for built-in types). Making it so that you can't
add overloaded operators anywhere but directly to the type
itself helps minimize that abuse (though there are certainly
folks who would like to do it, and there have been discussions
/ arguments about it in the past).
And honestly, concatenating a string and an integer is exactly
the sort of thing that D was trying to avoid - and it's also
why ~ is used for concatenation rather than +, because
otherwise there's potentially confusion over stuff like `"1" +
"2"` (e.g. should it be "12" or "3"?). Adding the ability to do
`"1" ~ 2` would be similarly confusing. Should 2 be treated as
"2", or should it be treated as `cast(char) 2` (or `cast(dchar)
2`, though with a number that small, it would be the same
thing)?
In general, the point of overloaded operators is to make it so
that user-defined types can have some of the same operations as
built-in types with semantics which are consistent with those
operators for built-in types. There are cases where that could
be done with overloaded operators defined outside of the type
if that were allowed, but changing how an operator works for a
built-in type definitely goes against what the ability to
overload operators is intended for.
- Jonathan M Davis
Well that was nicely explained.
I wonder if this kind of explanation should be added to the
manual.
Thanks,
Matheus.