Jump to page: 1 2
Thread overview
how to access struct member using [] operator?
Sep 25, 2016
grampus
Sep 25, 2016
Nicholas Wilson
Sep 25, 2016
Basile B.
Sep 25, 2016
Namespace
Sep 25, 2016
Lodovico Giaretta
Sep 25, 2016
grampus
Sep 25, 2016
Basile B.
Sep 25, 2016
Basile B.
Sep 25, 2016
Basile B.
Sep 25, 2016
ag0aep6g
Sep 26, 2016
pineapple
Sep 25, 2016
pineapple
Sep 25, 2016
grampus
Sep 26, 2016
ZombineDev
September 25, 2016
Dear all

For example, I have a struct
struct point{int x;int y}
point a;

Is there an easy way to access x and y by using a["x"] and a["y"]

I guess I need to overload [], but can't figure out how.

Someone can help? Thank you very much


September 25, 2016
On Sunday, 25 September 2016 at 04:54:31 UTC, grampus wrote:
> Dear all
>
> For example, I have a struct
> struct point{int x;int y}
> point a;
>
> Is there an easy way to access x and y by using a["x"] and a["y"]
>
> I guess I need to overload [], but can't figure out how.
>
> Someone can help? Thank you very much

The way you access the memers of a struct is through the dot syntax.

i.e.

a.x = a.y;

> Is there an easy way to access x and y by using a["x"] and a["y"]

in this case "x" and "y" are strings so no.
September 25, 2016
On Sunday, 25 September 2016 at 04:54:31 UTC, grampus wrote:
> Dear all
>
> For example, I have a struct
> struct point{int x;int y}
> point a;
>
> Is there an easy way to access x and y by using a["x"] and a["y"]
>
> I guess I need to overload [], but can't figure out how.
>
> Someone can help? Thank you very much

You can't do that. There's a problem because the string passed is not known at compile-time, so the return type of "opIndex(string member)" cannot be inferred.

It works only for one type:

°°°°°°°°°°°°°°°°°°°
import std.stdio;

struct Something
{
    int x,y;
    float z;

    int opIndex(string member)
    {
        alias T = typeof(this);
        foreach(m;__traits(allMembers, T))
        if (m == member)
        {
            static if (is(typeof(__traits(getMember, T, m)) == int))
                return __traits(getMember, T, m);
        }
        assert(0);
    }
}

void main(string[] args)
{
    Something s;
    writeln(s["x"]);
}
°°°°°°°°°°°°°°°°°°°

If you add a template parameter to opIndex then you can't call it with the array syntax so it becomes pointless to use an operator overload.
September 25, 2016
On Sunday, 25 September 2016 at 04:54:31 UTC, grampus wrote:
> Dear all
>
> For example, I have a struct
> struct point{int x;int y}
> point a;
>
> Is there an easy way to access x and y by using a["x"] and a["y"]
>
> I guess I need to overload [], but can't figure out how.
>
> Someone can help? Thank you very much

----
import std.stdio;

struct Something
{
    int x, y;
    float z;

    auto opIndex()(string member) {
		switch (member) {
			case "x": return this.x;
			case "y": return this.y;
			case "z": return this.z;
			default: assert(0);
		}
    }
}

void main(string[] args)
{
    Something s;
    writeln(s["x"]);
    writeln(s["z"]);
}
----
September 25, 2016
On Sunday, 25 September 2016 at 09:01:44 UTC, Namespace wrote:
> ----
> import std.stdio;
>
> struct Something
> {
>     int x, y;
>     float z;
>
>     auto opIndex()(string member) {
> 		switch (member) {
> 			case "x": return this.x;
> 			case "y": return this.y;
> 			case "z": return this.z;
> 			default: assert(0);
> 		}
>     }
> }
>
> void main(string[] args)
> {
>     Something s;
>     writeln(s["x"]);
>     writeln(s["z"]);
> }
> ----

Doesn't work. s["x"] is returned as float in this example. The reason is, opIndex cannot magically change return type based on the passed-in string.
September 25, 2016
On Sunday, 25 September 2016 at 04:54:31 UTC, grampus wrote:
> Dear all
>
> For example, I have a struct
> struct point{int x;int y}
> point a;
>
> Is there an easy way to access x and y by using a["x"] and a["y"]
>
> I guess I need to overload [], but can't figure out how.
>
> Someone can help? Thank you very much

If they all share the same type, you can use a switch like @Namespace suggested.

If the "x" and "y" strings are available at compile-time, you can use a mixin.

    auto getattr(string attr)(point a){
        mixin(`return a.` ~ attr ~ `;);
    }

    auto x = a.attr!"x";

Otherwise, no. D types aren't dynamic in the same way that Python's types are.
September 25, 2016
On Sunday, 25 September 2016 at 10:44:38 UTC, pineapple wrote:
> On Sunday, 25 September 2016 at 04:54:31 UTC, grampus wrote:
>> Dear all
>>
>> For example, I have a struct
>> struct point{int x;int y}
>> point a;
>>
>> Is there an easy way to access x and y by using a["x"] and a["y"]
>>
>> I guess I need to overload [], but can't figure out how.
>>
>> Someone can help? Thank you very much
>
> If they all share the same type, you can use a switch like @Namespace suggested.
>
> If the "x" and "y" strings are available at compile-time, you can use a mixin.
>
>     auto getattr(string attr)(point a){
>         mixin(`return a.` ~ attr ~ `;);
>     }
>
>     auto x = a.attr!"x";
>
> Otherwise, no. D types aren't dynamic in the same way that Python's types are.

Thank you all for the clear reply.

Now I know how far I can go on this.

September 25, 2016
On Sunday, 25 September 2016 at 09:01:44 UTC, Namespace wrote:
> On Sunday, 25 September 2016 at 04:54:31 UTC, grampus wrote:
>> Dear all
>>
>> For example, I have a struct
>> struct point{int x;int y}
>> point a;
>>
>> Is there an easy way to access x and y by using a["x"] and a["y"]
>>
>> I guess I need to overload [], but can't figure out how.
>>
>> Someone can help? Thank you very much
>
> ----
> import std.stdio;
>
> struct Something
> {
>     int x, y;
>     float z;
>
>     auto opIndex()(string member) {
> 		switch (member) {
> 			case "x": return this.x;
> 			case "y": return this.y;
> 			case "z": return this.z;
> 			default: assert(0);
> 		}
>     }
> }
>
> void main(string[] args)
> {
>     Something s;
>     writeln(s["x"]);
>     writeln(s["z"]);
> }
> ----

I think this approach should work for me.
Thank you Namespace:)
September 25, 2016
On Sunday, 25 September 2016 at 09:01:44 UTC, Namespace wrote:
> On Sunday, 25 September 2016 at 04:54:31 UTC, grampus wrote:
>> Dear all
>>
>> For example, I have a struct
>> struct point{int x;int y}
>> point a;
>>
>> Is there an easy way to access x and y by using a["x"] and a["y"]
>>
>> I guess I need to overload [], but can't figure out how.
>>
>> Someone can help? Thank you very much
>
> ----
> import std.stdio;
>
> struct Something
> {
>     int x, y;
>     float z;
>
>     auto opIndex()(string member) {
> 		switch (member) {
> 			case "x": return this.x;
> 			case "y": return this.y;
> 			case "z": return this.z;
> 			default: assert(0);
> 		}
>     }
> }
>
> void main(string[] args)
> {
>     Something s;
>     writeln(s["x"]);
>     writeln(s["z"]);
> }
> ----

WooW I have to say that I'm mesmerized !

How can this works ? "member" is run time variable so the return type shouldn't be inferable.
September 25, 2016
On Sunday, 25 September 2016 at 16:07:59 UTC, Basile B. wrote:
> On Sunday, 25 September 2016 at 09:01:44 UTC, Namespace wrote:
>> On Sunday, 25 September 2016 at 04:54:31 UTC, grampus wrote:
>>> Dear all
>>>
>>> For example, I have a struct
>>> struct point{int x;int y}
>>> point a;
>>>
>>> Is there an easy way to access x and y by using a["x"] and a["y"]
>>>
>>> I guess I need to overload [], but can't figure out how.
>>>
>>> Someone can help? Thank you very much
>>
>> ----
>> import std.stdio;
>>
>> struct Something
>> {
>>     int x, y;
>>     float z;
>>
>>     auto opIndex()(string member) {
>> 		switch (member) {
>> 			case "x": return this.x;
>> 			case "y": return this.y;
>> 			case "z": return this.z;
>> 			default: assert(0);
>> 		}
>>     }
>> }
>>
>> void main(string[] args)
>> {
>>     Something s;
>>     writeln(s["x"]);
>>     writeln(s["z"]);
>> }
>> ----
>
> WooW I have to say that I'm mesmerized !
>
> How can this works ? "member" is run time variable so the return type shouldn't be inferable.

Ther's no trick related to compile time:

import std.stdio;

 struct Something
 {
     int y;
     float z;
     double e;
     float x = 1234;

     auto opIndex()(const(char)[] member) {
 		switch (member) {
 			case "x": return this.x;
 			case "y": return this.y;
 			case "z": return this.z;
            case "e": return this.e;
 			default: assert(0);
 		}
     }
 }

 void main(string[] args)
 {
     Something s;
     char[] member = "w".dup;
     member[0]  += args.length;
     writeln(s[member]);
 }

Can we get an explanation from a compiler guy ? It seems the the switch statement is already evaluated at compiled time...
« First   ‹ Prev
1 2