On 10/15/12 17:49, Maxim Fomin wrote: > 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.
Actually, I'm not really in any camp. UFCS has several obvious problems plus likely quite a few more subtle ones. Ignoring the issues does not make them go away and the some-compiler-happens-to-implement-it-like-that-today-therefore-thats-how-it- -must-work arguments, that often appear here, do not really help. Note that my above "UFCS method must take precedence" statement only describes the required functionality; handling it like that /by default/ wouldn't probably be a good idea, as that would make accidental method hijacking possible. The lookup should be more like - T.method - ufcs_method(T) marked with 'override' - while (T = alias this) { - T.method - ufcs_method(T) marked with 'override' } - ufcs_method(T) w/o 'override' - while (T = alias this) - ufcs_method(T) w/o 'override' with the compiler enforcing the obvious 'override' rules for ufcs_method declarations (requiring that T isn't opaque when declaring (or calling) UFCS functions is reasonable, i don't think having 'foo(a)' and 'a.foo()' mean completely different things would work well together with UFCS). And yes, it wouldn't completely eliminate the possibility of hijacking - but you'd need three components interacting for it to happen, which would make it much less likely to occur. [Note i came up w/ this design while writing this email - it's not necessarily perfect.] >> And the purpose of UFCS is?... "operator overloading methods" are /not/ >> special. > > 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. This is how UFCS works - for "normal" methods. There's no reason to handle op overloads or other special methods differently. You are arguing for introducing arbitrary restrictions, which would bring no gain (that i can see right now), but disallow useful functionality. Yes, there are some issues, but those are not op-overload specific, but UFCS-related. > 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. Well, i don't think anybody wants to /override/ existing operators - it's only about allowing /extending/ the functionality of non-local types, by adding support for additional ops and/or types. While being able to override existing methods with UFCS would have some uses, allowing that would also introduce additional problems. Anyway, if you need to modify how a type's existing ops work you can always sub-type - this is also true in the (non-virtual) method case; UFCS is basically just syntax sugar (which allows you to transparently locally inject methods w/o creating a new type, downcasting and handling the (implicit) upcasts (which could be problematic when eg working with (pointers-to-)structs)). artur