digitalmars.D.learn - Static indexing
- JG (18/18) Jan 12 2022 Hi,
- Ali Cehreli (30/32) Jan 12 2022 std.typecons.Tuple already does that. You can add "member functions"
- Steven Schveighoffer (15/36) Jan 12 2022 I was going to reply that you can't do it this way, but it works. Very
- H. S. Teoh (10/23) Jan 12 2022 [...]
Hi, I want to make a type which has two fields x and y but can also be indexed with [0] and [1] checked at compile time. Is the following reasonable / correct? struct Point { double x; double y; alias expand = typeof(this).tupleof; alias expand this; } unittest { Point p = Point(1.2,3.4); assert(p[0]==1.2); assert(p[1]==3.4); assert(!__traits(compiles,Point.init[3])); }
Jan 12 2022
On 1/12/22 00:59, JG wrote:I want to make a type which has two fields x and y but can also be indexed with [0] and [1] checked at compile time.std.typecons.Tuple already does that. You can add "member functions" like foo() below by taking advantage of UFCS: import std.typecons; alias Point = Tuple!(double, "x", double, "y"); unittest { Point p = Point(1.25,3.5); assert(p[0]==1.25); assert(p.x==1.25); assert(p[1]==3.5); assert(p.y==3.5); assert(!__traits(compiles,Point.init[3])); } void foo(ref Point p) { p.x += p.y; } unittest { auto p = Point(1.5, 2.75); p.foo(); assert(p.x == 4.25); assert(p.y == 2.75); } void main() { } Also note, I changed all the floating point values to ones that can be fully representable by floating point types so that the unit tests would always succeed. (For example, 0.1 and 0.4 etc. cannot be represented fully but 0.5 and 0.25 etc. can be.) Ali
Jan 12 2022
On 1/12/22 3:59 AM, JG wrote:Hi, I want to make a type which has two fields x and y but can also be indexed with [0] and [1] checked at compile time. Is the following reasonable / correct?    struct Point    {      double x;      double y;      alias expand = typeof(this).tupleof;      alias expand this;    }    unittest    {      Point p = Point(1.2,3.4);      assert(p[0]==1.2);      assert(p[1]==3.4);      assert(!__traits(compiles,Point.init[3]));    }I was going to reply that you can't do it this way, but it works. Very interesting! I would say to go with that, and I love that technique! Seems like it started allowing alias to `tupleof` in 2.094. `std.typecons.Tuple` does it much differently. It declares the tuple as an alias-this'd member, and then defines named accessors for each of the items (if you give them names). One thing I did find is that foreach doesn't like your mechanism, whereas the Tuple mechanism does work: ```d foreach(x, y; only(Point(1.0, 2.0)) {} // error foreach(x, y; only(tuple(1.0, 2.0)) {} // ok ``` -Steve
Jan 12 2022
On Wed, Jan 12, 2022 at 11:04:59AM -0500, Steven Schveighoffer via Digitalmars-d-learn wrote:On 1/12/22 3:59 AM, JG wrote:[...][...]struct Point { double x; double y; alias expand = typeof(this).tupleof; alias expand this; }I was going to reply that you can't do it this way, but it works. Very interesting! I would say to go with that, and I love that technique! Seems like it started allowing alias to `tupleof` in 2.094.[...] Yeah, I was also going to say, this is a very interesting trick indeed! I might actually adopt this for one of my projects, instead of the more complex CTFE-generated mixin I'm currently using. T -- Making non-nullable pointers is just plugging one hole in a cheese grater. -- Walter Bright
Jan 12 2022