digitalmars.dip.ideas - Enhanced UFCS
- xoxo (45/45) May 26 # Improving UFCS for Pointers to Structs
- Steven Schveighoffer (5/10) May 26 So the biggest caveat I see is if there are multiple options. I
- Dennis (18/19) May 26 I've encountered this limitation as well, and like this idea of
- Kagamin (6/9) May 27 I think, it works only for local variables.
- monkyyy (29/30) May 26 I think overload resulation is a big old mess and even small asks
I’ve often found myself avoiding UFCS in D simply because I couldn’t use it consistently. The compiler forces me to duplicate functions when working with both values and pointers, which defeats a lot of the elegance UFCS is supposed to provide. Here’s a minimal example: ```d struct Vector { int data; } void add(ref Vector self, int value) { self.data += value; } void main() { Vector v; Vector* ptr = &v; v.add(1); // Works ptr.add(1); // Error: no matching function } ``` The ptr.add(1) line fails because UFCS doesn’t automatically dereference the pointer to match the ref parameter in add. To make it work, I’d need to either call add(*ptr, 1) or duplicate the function to handle Vector*. Neither option feels ideal. Could D support automatic UFCS for pointers to structs? That is, allow the compiler to transform ptr.add(1) into add(*ptr, 1) if the function takes a ref and ptr is a pointer to the expected type. This would make UFCS much more usable without changing any behavior for existing code. Maybe this could be enabled via auto ref, inout ref, or something similar if implicit dereferencing is too risky to do universally. In Zig, for example, UFCS works seamlessly whether you have a value or a pointer — the compiler just figures it out. That kind of polish would be great to see in D as well. Less boilerplate Better parity with languages like Zig No need to manually unwrap pointers just to get method-like syntax
May 26
On Monday, 26 May 2025 at 07:55:20 UTC, xoxo wrote:I’ve often found myself avoiding UFCS in D simply because I couldn’t use it consistently. The compiler forces me to duplicate functions when working with both values and pointers, which defeats a lot of the elegance UFCS is supposed to provide.So the biggest caveat I see is if there are multiple options. I would say this counts as a conversion for purposes of overloading. Looks good to me though, well stated. -Steve
May 26
I've encountered this limitation as well, and like this idea of more uniformity. But as Steven said, care needs to be taken with overloads: ```D // foo.d int f(S* x) => 2; // in an imported module // bar.d import foo; int f(ref S x) => 1; // in this module S* ptr; void main() { writeln(ptr.f); // 1 or 2? } ``` On Monday, 26 May 2025 at 07:55:20 UTC, xoxo wrote:Here’s a minimal example:As of 2.111, you can do `ref Vector ptr = v;` instead of using a pointer, so perhaps you can use a different motivating example.
May 26
On Monday, 26 May 2025 at 14:18:36 UTC, Dennis wrote:As of 2.111, you can do `ref Vector ptr = v;` instead of using a pointer, so perhaps you can use a different motivating example.I think, it works only for local variables. ``` char*[] args; args[0].strlen; ```
May 27
On Monday, 26 May 2025 at 07:55:20 UTC, xoxo wrote:I think overload resulation is a big old mess and even small asks will break stuff unexpectedly. This could be thrown to the bottom of the list of is 6(?) rules and then only stuff using compiles check would break, but that would reduce its scaling drasticly and would still be a fight. also: ```d struct Vector { int data; } void add(T)(ref T self, int value)//<-- { self.data += value; } void main() { Vector v; Vector* ptr = &v; v.add(1); // Works ptr.add(1); // also works } ``` Id suggest trying for either: a) reusing the property keyword for ufcs functions to modify overload resulation(in my opinion the rules are exactly backwards) b) adding a type specailization that matches for T and T* c) ufcs perfers a named argument of "self"/"ufcs"/"this"
May 26