www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Static indexing

reply JG <someone somewhere.com> writes:
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
next sibling parent Ali Cehreli <acehreli yahoo.com> writes:
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
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
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
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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