Quickly fork, edit online, and submit a pull request for this page.
Requires a signed-in GitHub account. This works well for small changes.
If you'd like to make larger changes you may want to consider using
a local clone.

This is the way C++ does it, and it is appealing to be able
to refer to overloading ‘+’ with ‘operator+’. The trouble is
things don't quite fit. For example, there are the
comparison operators <, <=, >, and >=. In C++, all four must
be overloaded to get complete coverage. In D, only an opCmp()
function must be defined, and the comparison operations are
derived from that by semantic analysis.

Further, binary operators on number-based types are largely uniformly
implemented so a single opBinary template allows one to just mixin the
operator the user used, whereas in C++ each operator will need to be separately
defined. For example:

Operator overloading can only be done with an argument
as an object, so they logically belong as member functions
of that object. That does leave the case of what to do
when the operands are objects of different types:

class A { }
class B { }
int opAdd(class A, class B);

Should opAdd() be in class A or B? The obvious stylistic solution
would be to put it in the class of the first operand,

class A
{
int opAdd(class B) { }
}

Operator overloads usually need access to private members
of a class, and making them global breaks the object oriented
encapsulation of a class.

(2) can be addressed by operator overloads automatically gaining
"friend" access, but such unusual behavior is at odds with D
being simple.

These can be very useful for attaching new infix operations
to various unicode symbols. The trouble is that in D,
the tokens are supposed to be completely independent of the
semantic analysis. User definable operators would break that.

This means that the operator overload cannot be virtual, and
so likely would be implemented as a shell around another
virtual function to do the real work. This will wind up looking
like an ugly hack. Secondly, the opCmp() function is already
an operator overload in Object, it needs to be virtual for several
reasons, and making it asymmetric with the way other operator
overloads are done is unnecessary confusion.

Let's rephrase that as “if there's a way to express it in the existing
language, why build it in to the core language?”
In regards to T.infinity:

Building it in to the core language means the core language knows
what a floating point infinity is. Being layered in templates, typedefs,
casts, const bit patterns, etc., it doesn't know what it is, and is
unlikely to give sensible error messages if misused.

A side effect of (1) is it is unlikely to be able to use it
effectively in constant folding and other optimizations.

The worst, though, is the lengths gone to just to get at infinity,
implying “the language and compiler don't know anything about IEEE 754
floating point - so it cannot be relied on.” And in fact
many otherwise excellent C++ compilers
do not handle NaN's correctly in floating point comparisons.
(Digital Mars C++ does do it correctly.)
C++98 doesn't say anything about NaN or Infinity handling in expressions
or library functions. So it must be assumed it doesn't work.

To sum up, there's a lot more to supporting NaNs and infinities than
having a template that returns a bit pattern. It has to be built in to
the compiler's core logic, and it has to permeate all the library code
that deals with floating point. And it has to be in the Standard.