Operator overloading through UFCS doesn't work
Maxim Fomin
maxim at maxim-fomin.ru
Mon Oct 15 08:49:59 PDT 2012
On Monday, 15 October 2012 at 11:01:13 UTC, Artur Skawina wrote:
> UFCS has pros and cons. I could agree that it has problems and
> should be removed
> from the language completely. But if the feature is there, it
> should work, w/o any
> unnecessary special cases.
Special cases would be created by any decision, the only question
is which feature is discriminated - alias this, UFCS or something
else (currently UFCS is).
> An overloaded operator is just another normal method; you get
> the same type of
> problems when dealing with "normal" methods - eg in types
> having an "alias this" -
> an UFCS "method" must take precedence over one reachable via
> the alias - just like
> in the overloaded op case. The only sane alternative would be
> disallowing UFCS
> for types with an "alias this" (which would be a severe
> limitation).
You seem to be in the second camp (UFCS free function takes
precedence over alias this, if declared). I am not against, just
to note.
> And the purpose of UFCS is?... "operator overloading methods"
> are /not/ special.
> artur
The point is that when you want to define UFCS free functions
like opUnary, you want not only to call them like
a.opUnary!"++"() but to code like ++a. That is the key issue here
and that makes the whole case special.
In other words: with UFCS you have an option: to call your
function as it was a method of some type. And anyone has this
option. The only problem is namespace conflict which can be
easily avoided. But you still has the option.
With UFCS operator overloaded functions you have *two* options:
to call free functions as methods as usual *and* to use
struct/class with many operators in a manner you want. But if
anyone of that type users define his set of operator overloaded
functions *you lose the second option* which makes the proposal
to allow simultaneous access to single resource pointless.
Consider this:
---somelib.d---
struct A { void foo() {} }
---otherlib.d---
void bar(A a) {}
---mycode.d---
// blah, foo and bar are taken
// solution - choose other name
void baz(A a) {}
---------------
Now assume, UFCS operator overload is possible.
---somelib.d---
struct A { int i; int j; }
---mycode.d---
int opUnary(string T : "++")()
{
return ++i;
}
...
++a;
...
-------------
At some point of time the owner of somelib.d changes code (or
anyone whom code you import define such functions):
---somelib.d---
struct A {
int i; int j;
int opUnary(string T : "++")()
{
return ++j;
}
}
---mycode.d---
int opUnary(string T : "++")()
{
return ++i;
}
----------------
So, you lost your option to use A in expressions and call your
function which is the point here. You cannot invent +my_unary+
operator. Neither you can rebind ++ to some function other than
opUnary.
Yes, it also may happen with regular function, when you lose
ability to give a function some specific name you want (like
"create", "foo" etc.). But in case of UFCS operators you lose not
only some function name ("opUnary") but corresponding expression
as well (++).
This means that it makes sense to allow only one set of
opUnary/opBinary/.. etc. of functions (anyway, only one can
define them and use with operators) and the most suitable place
is declaration of their type.
More information about the Digitalmars-d-learn
mailing list