www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Making alias of a struct field needs "this".

reply realhet <real_het hotmail.com> writes:
Hello,

I have a 2 level nested struct structure with nice descriptive 
field names.
And I thought it will be easy to alias those identifierLists with 
a few letter names and do some calculations on them.
But I'm having an error.

struct A{
   struct B{ int c; }
   B b;

   auto f(){
     alias d = b.c;
     return d;  //Compiler Error: need 'this' for c of type int.
   }
}

There's the this and it's called "b."

Why is this? If I copy paste the aliased expression "b.c", it 
compiled fine.

Thanks in advance!
Jun 02 2020
next sibling parent reply Basile B. <b2.temp gmx.com> writes:
On Tuesday, 2 June 2020 at 08:56:13 UTC, realhet wrote:
 Hello,

 I have a 2 level nested struct structure with nice descriptive 
 field names.
 And I thought it will be easy to alias those identifierLists 
 with a few letter names and do some calculations on them.
 But I'm having an error.

 struct A{
   struct B{ int c; }
   B b;

   auto f(){
     alias d = b.c;
     return d;  //Compiler Error: need 'this' for c of type int.
   }
 }

 There's the this and it's called "b."

 Why is this? If I copy paste the aliased expression "b.c", it 
 compiled fine.

 Thanks in advance!
There's a language rule, expressions cant be aliased, however D has a bug, some expressions that look like type can be aliased, then when you use them you have an error about 'this' but in first place here you should really have an error saying 'cant alias expression'.
Jun 02 2020
parent Basile B. <b2.temp gmx.com> writes:
On Tuesday, 2 June 2020 at 09:07:08 UTC, Basile B. wrote:
 On Tuesday, 2 June 2020 at 08:56:13 UTC, realhet wrote:
 [...]
There's a language rule, expressions cant be aliased, however D has a bug, some expressions that look like type can be aliased, then when you use them you have an error about 'this' but in first place here you should really have an error saying 'cant alias expression'.
Note that most of the time attempts to alias expressions is detected. This is a particular bug, a "corner case".
Jun 02 2020
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 6/2/20 1:56 AM, realhet wrote:

 struct A{
    struct B{ int c; }
    B b;

    auto f(){
      alias d = b.c;
The spec explicitly says it's not legal: "Aliases cannot be used for expressions" (Item 10): https://dlang.org/spec/declaration.html#alias I use nested functions for such cases: auto f(){ auto d() { return b.c; } return d; } Ali
Jun 02 2020
parent reply realhet <real_het hotmail.com> writes:
On Tuesday, 2 June 2020 at 09:10:03 UTC, Ali Çehreli wrote:
 On 6/2/20 1:56 AM, realhet wrote:

 struct A{
    struct B{ int c; }
    B b;

    auto f(){
      alias d = b.c;
The spec explicitly says it's not legal: "Aliases cannot be used for expressions" (Item 10): https://dlang.org/spec/declaration.html#alias I use nested functions for such cases: auto f(){ auto d() { return b.c; } return d; } Ali
Thanks for responses: I did it that way: private enum fieldMap = [ // simple names for descriptive and structured fields "hauteur" : "general.height", "rayon" : "profile.radius", "plage" : "profile.plage", "offsetv" : "profile.verticalOffset", "offseth" : "profile.horizontalOffset", "varrad0" : "profile.linearVariationBottom", "varrad1" : "profile.linearVariationTop", "amplitude" : "periphery.amplitude", "varlin0" : "periphery.linearVariationBottom", "varlin1" : "periphery.linearVariationTop", "varsinp" : "periphery.cosinusVariationPlage", "varsino" : "periphery.cosinusVariationOffset", "periodes" : "periphery.nbPeriods", "revolution" : "periphery.turn" ]; static foreach(k, v; fieldMap){ mixin(" property auto $() i know -> AliasSeq :D But it doesn't look nice. I've found some additional info here: https://forum.dlang.org/thread/hresorfqicczofnrccpl forum.dlang.org?page=2 Seems like I must not except the same from an alias template paramater and from the alias construct. The alias construct is for a single symbol.
Jun 02 2020
next sibling parent realhet <real_het hotmail.com> writes:
On Tuesday, 2 June 2020 at 09:28:01 UTC, realhet wrote:
 On Tuesday, 2 June 2020 at 09:10:03 UTC, Ali Çehreli wrote:
 On 6/2/20 1:56 AM, realhet wrote:
Oh and I can put that function generator mixin thing into a template as well, that way it is reusable and much nicer. There are a lot of possibilities in D, I love it!
Jun 02 2020
prev sibling next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Tuesday, 2 June 2020 at 09:28:01 UTC, realhet wrote:
   static foreach(k, v; fieldMap){ mixin(" property auto $() 

 know, i know -> AliasSeq :D
You can use std.format.format to do it in one function call: mixin(" property auto %s() const { return %s; }".format(k, v)); Or just put `k` and `v` directly into the mixin: mixin(" property auto ", k, "() const { return ", v, "; }");
Jun 02 2020
parent reply realhet <real_het hotmail.com> writes:
On Tuesday, 2 June 2020 at 13:10:55 UTC, Paul Backus wrote:
 On Tuesday, 2 June 2020 at 09:28:01 UTC, realhet wrote:
     mixin(" property auto ", k, "() const { return ", v, "; }");
Wow, string mixin can process comma separated list, I gotta remember this, thanks!
Jun 02 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 6/2/20 10:51 AM, realhet wrote:
 On Tuesday, 2 June 2020 at 13:10:55 UTC, Paul Backus wrote:
 On Tuesday, 2 June 2020 at 09:28:01 UTC, realhet wrote:
     mixin(" property auto ", k, "() const { return ", v, "; }");
Wow, string mixin can process comma separated list, I gotta remember this, thanks!
Indeed, I too did not know about this! I generally do a ~ b ~ c, not worrying about performance since it's compile time, but this requires that you do the conversion to string yourself. In some cases, it's a requirement since what the compiler does to convert to a string may not be what you want. But something like mixin("int a = ", adefault, ";"); is much better than import std.format; mixin(format("int a = %s;" adefault)); I will have to remember this. I recently found out that pragma(msg) has the same capability. -Steve
Jun 02 2020
parent reply realhet <real_het hotmail.com> writes:
On Tuesday, 2 June 2020 at 20:38:40 UTC, Steven Schveighoffer 
wrote:
 On 6/2/20 10:51 AM, realhet wrote:
 On Tuesday, 2 June 2020 at 13:10:55 UTC, Paul Backus wrote:
 On Tuesday, 2 June 2020 at 09:28:01 UTC, realhet wrote:
A month ago I discovered that mixinDeclarations can be used for types too: mixin("int[", 2, "]") a = [5, 6];
Jun 03 2020
parent realhet <real_het hotmail.com> writes:
On Wednesday, 3 June 2020 at 10:11:59 UTC, realhet wrote:
 On Tuesday, 2 June 2020 at 20:38:40 UTC, Steven Schveighoffer 
 wrote:
 On 6/2/20 10:51 AM, realhet wrote:
 On Tuesday, 2 June 2020 at 13:10:55 UTC, Paul Backus wrote:
 On Tuesday, 2 June 2020 at 09:28:01 UTC, realhet wrote:
mixin("int[", 2, "]") a = mixin([5]) ~ 6; That's insane :D
Jun 03 2020
prev sibling parent reply Stanislav Blinov <stanislav.blinov gmail.com> writes:
On Tuesday, 2 June 2020 at 09:28:01 UTC, realhet wrote:

 I did it that way:
   private enum fieldMap = [ // simple names for descriptive and 
 structured fields
     "hauteur"       : "general.height",
     "rayon"         : "profile.radius",
     "plage"         : "profile.plage",
     "offsetv"       : "profile.verticalOffset",
     "offseth"       : "profile.horizontalOffset",
     "varrad0"       : "profile.linearVariationBottom",
     "varrad1"       : "profile.linearVariationTop",
     "amplitude"     : "periphery.amplitude",
     "varlin0"       : "periphery.linearVariationBottom",
     "varlin1"       : "periphery.linearVariationTop",
     "varsinp"       : "periphery.cosinusVariationPlage",
     "varsino"       : "periphery.cosinusVariationOffset",
     "periodes"      : "periphery.nbPeriods",
     "revolution"    : "periphery.turn"
   ];

   static foreach(k, v; fieldMap){ mixin(" property auto $() 

 know, i know -> AliasSeq :D

 But it doesn't look nice.
Try UDAs instead of a map: struct A { struct G { ("hauteur") int height; } struct P { ("rayon") int radius; ("plage") int plage; ("offsetv") int verticalOffset; ("offseth") int horizontalOffset; int noShortcut; ("varrad0") int linearVariationBottom; } G general; P profile; /* ... */ static foreach (i, m; typeof(this).tupleof) static foreach (j, f; typeof(m).tupleof) static if (__traits(getAttributes, f).length) mixin(" property auto ", __traits(getAttributes, f)[0], "() const { return this.tupleof[i].tupleof[j]; }"); } pragma(msg, __traits(allMembers, A));
Jun 02 2020
parent realhet <real_het hotmail.com> writes:
On Tuesday, 2 June 2020 at 13:37:25 UTC, Stanislav Blinov wrote:
 On Tuesday, 2 June 2020 at 09:28:01 UTC, realhet wrote:
 Try UDAs instead of a map:

 struct A {
     struct G {
          ("hauteur") int height;
     }
Good idea, thx! I already using UDA's for range and measurement units. struct Profile{ STORED: UNIT("mm") RANGE(0, 100) float radius = 21; I gonna need one more reasonably named UDA struct.
Jun 02 2020