www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - alias restriction??!

reply Carl Sturtivant <sturtivant gmail.com> writes:
Here's a toy version of a problem in the wild.

struct S {
     long first;
     union T {
         long one;
         double two;
     }
     T second;
     alias First = first;
     alias Second = second.one;
}

void main() {
     S x;
     x.First = 4;
     x.Second = 5; // compilation error: "Error: need this for one 
of type long"
}

Second is a fixed offset into an S and it would be nice to have a 
name for it. Why doesn't alias know it's OK?

I can work around this with some duplication as follows.

struct S {
     long first;
     union {
         long one;
         double two;
         union T {
             long one;
             double two;
         }
         T second;
     }
     alias First = first;
     alias Second = one;
}

void main() {
     S x;
     x.First = 4;
     x.Second = 5;
     x.second.one = 6;
     import std.stdio;
     writeln(x);
     writeln(x.one);
     writeln(x.Second);
}

Is there any way to avoid the duplication of the entries in the 
anonymous union, aside from using a mixin template?

Is there some other way (not involving writing a function) to 
work around this?
Jul 18 2020
next sibling parent reply Dennis <dkorpel gmail.com> writes:
On Saturday, 18 July 2020 at 18:46:16 UTC, Carl Sturtivant wrote:
 Is there any way to avoid the duplication of the entries in the 
 anonymous union, aside from using a mixin template?
I think this would be fixed if https://github.com/dlang/dmd/pull/11273 gets merged.
Jul 18 2020
parent Basile B. <b2.temp gmx.com> writes:
On Saturday, 18 July 2020 at 22:49:18 UTC, Dennis wrote:
 On Saturday, 18 July 2020 at 18:46:16 UTC, Carl Sturtivant 
 wrote:
 Is there any way to avoid the duplication of the entries in 
 the anonymous union, aside from using a mixin template?
I think this would be fixed if https://github.com/dlang/dmd/pull/11273 gets merged.
The feature still needs some work. With this PR aliases of members only works when they are declared in a function scope and not in the aggregate scope. Example: --- struct Inner { int a; } struct TopLevel { Inner inner; alias ia = inner.a; } void main() { TopLevel tl; alias ia = tl.inner.a; ia = 42; // OK with PR 11273 tl.ia = 42; // NG Error: need `this` for `a` of type `int` } --- I think it's not good to merge until the second case works. Also it requires approval. For now it is specified that expressions cant be aliased.
Jul 18 2020
prev sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Saturday, 18 July 2020 at 18:46:16 UTC, Carl Sturtivant wrote:
 Here's a toy version of a problem in the wild.

 struct S {
     long first;
     union T {
         long one;
         double two;
     }
     T second;
     alias First = first;
     alias Second = second.one;
 }

 void main() {
     S x;
     x.First = 4;
     x.Second = 5; // compilation error: "Error: need this for 
 one of type long"
 }
Easiest workaround: ref inout(long) Second() inout { return second.one; }
Jul 19 2020
parent reply Carl Sturtivant <sturtivant gmail.com> writes:
On Sunday, 19 July 2020 at 12:08:07 UTC, Paul Backus wrote:
 On Saturday, 18 July 2020 at 18:46:16 UTC, Carl Sturtivant 
 wrote:
 Here's a toy version of a problem in the wild.

 struct S {
     long first;
     union T {
         long one;
         double two;
     }
     T second;
     alias First = first;
     alias Second = second.one;
 }

 void main() {
     S x;
     x.First = 4;
     x.Second = 5; // compilation error: "Error: need this for 
 one of type long"
 }
Easiest workaround: ref inout(long) Second() inout { return second.one; }
Was trying to avoid this for performance reasons. In fact what are the performance implications of this sort of thing with current implementations? --- relative to using a simple offset.
Jul 19 2020
parent reply Paul Backus <snarwin gmail.com> writes:
On Sunday, 19 July 2020 at 12:42:47 UTC, Carl Sturtivant wrote:
 On Sunday, 19 July 2020 at 12:08:07 UTC, Paul Backus wrote:
 Easiest workaround:

 ref inout(long) Second() inout { return second.one; }
Was trying to avoid this for performance reasons. In fact what are the performance implications of this sort of thing with current implementations? --- relative to using a simple offset.
Almost certainly no difference at all. Even DMD can inline this function: https://d.godbolt.org/z/7ve6M8
Jul 19 2020
parent reply Basile B. <b2.temp gmx.com> writes:
On Sunday, 19 July 2020 at 15:00:59 UTC, Paul Backus wrote:
 On Sunday, 19 July 2020 at 12:42:47 UTC, Carl Sturtivant wrote:
 On Sunday, 19 July 2020 at 12:08:07 UTC, Paul Backus wrote:
 Easiest workaround:

 ref inout(long) Second() inout { return second.one; }
Was trying to avoid this for performance reasons. In fact what are the performance implications of this sort of thing with current implementations? --- relative to using a simple offset.
Almost certainly no difference at all. Even DMD can inline this function: https://d.godbolt.org/z/7ve6M8
The alias proposal matches to the "code fast" moto. When you do object composition with several level of nesting this would be a time saver.
Jul 19 2020
parent reply Paul Backus <snarwin gmail.com> writes:
On Sunday, 19 July 2020 at 16:00:28 UTC, Basile B. wrote:
 On Sunday, 19 July 2020 at 15:00:59 UTC, Paul Backus wrote:
 On Sunday, 19 July 2020 at 12:42:47 UTC, Carl Sturtivant wrote:
 On Sunday, 19 July 2020 at 12:08:07 UTC, Paul Backus wrote:
 Easiest workaround:

 ref inout(long) Second() inout { return second.one; }
Was trying to avoid this for performance reasons. In fact what are the performance implications of this sort of thing with current implementations? --- relative to using a simple offset.
Almost certainly no difference at all. Even DMD can inline this function: https://d.godbolt.org/z/7ve6M8
The alias proposal matches to the "code fast" moto. When you do object composition with several level of nesting this would be a time saver.
It replaces something that's already a one-liner with a slightly shorter one-liner. Color me unimpressed. Also, letting aliases refer to expressions essentially allows AST macros in through the back door. Consider the following example: template counter() { struct Counter { static size_t count; size_t next() { return count++; } } alias counter = Counter.init.next; } void main() { import std.stdio: writeln; writeln(counter!()); // 0 writeln(counter!()); // 1 writeln(counter!()); // 2 } This program compiles, runs, and prints the indicated output using the version of dmd built from the member-alias pull request [1]. Personally, I'm in favor of AST macros, but if we're going to add them to D, I think we should do it intentionally, rather than by accident, and there should be a DIP. [1] https://github.com/dlang/dmd/pull/11273
Jul 19 2020
parent reply Carl Sturtivant <sturtivant gmail.com> writes:
On Sunday, 19 July 2020 at 17:06:14 UTC, Paul Backus wrote:
 Also, letting aliases refer to expressions essentially allows 
 AST macros in through the back door. Consider the following 
 example:

 [...]
Perhaps what's needed is something more that is less than allowing aliases for expressions in the wide sense you suggest here.
Jul 19 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/19/20 4:21 PM, Carl Sturtivant wrote:
 On Sunday, 19 July 2020 at 17:06:14 UTC, Paul Backus wrote:
 Also, letting aliases refer to expressions essentially allows AST 
 macros in through the back door. Consider the following example:

 [...]
Perhaps what's needed is something more that is less than allowing aliases for expressions in the wide sense you suggest here.
I agree. Something not yet mentioned is that aliases provide direct access to the symbols for the purposes of looking at attributes -- something that a wrapper function doesn't provide. The question is: how do you restrict it to explicit data items within a specific aggregate without parsing arbitrary expressions? -Steve
Jul 19 2020
parent reply Carl Sturtivant <sturtivant gmail.com> writes:
On Sunday, 19 July 2020 at 20:46:19 UTC, Steven Schveighoffer 
wrote:
 On 7/19/20 4:21 PM, Carl Sturtivant wrote:
 
 Perhaps what's needed is something more that is less than 
 allowing aliases for expressions in the wide sense you suggest 
 here.
I agree. Something not yet mentioned is that aliases provide direct access to the symbols for the purposes of looking at attributes -- something that a wrapper function doesn't provide. The question is: how do you restrict it to explicit data items within a specific aggregate without parsing arbitrary expressions?
Well perhaps you do parse a "constant-offset expression" i.e. syntactically dotted with constant indexes, like name1.name2[constant].name3 and then later there's a semantic check that the "constant-offset expression" involves no indirections when an offset into the top level object is computed. Then it's treated like any other attribute of a struct with a known offset.
Jul 20 2020
parent Carl Sturtivant <sturtivant gmail.com> writes:
On Monday, 20 July 2020 at 17:24:56 UTC, Carl Sturtivant wrote:
 Well perhaps you do parse a "constant-offset expression" i.e. 
 syntactically dotted with constant indexes, like 
 name1.name2[constant].name3 and then later there's a semantic 
 check that the "constant-offset expression" involves no 
 indirections when an offset into the top level object is 
 computed. Then it's treated like any other attribute of a 
 struct with a known offset.
Perhaps this could also work for a class at the top with recursively embedded structs and value arrays.
Jul 20 2020