Supporting and signature-checking all foreach variations

Ali Çehreli acehreli at yahoo.com
Sun Feb 26 02:25:07 PST 2012


On 02/25/2012 08:25 AM, Ashish Myles wrote:
 > I want to define a general-purpose centroid computer for point containers
 > and ran into a couple of challenges. Firstly, here is the basic code
 >
 >      Point3 computeCentroid(PointContainer)(const ref PointContainer C)
 >          if (...)    // want a signature constraint for usability of 
foreach
 >      {
 >          Point3 c = Point3(0.0, 0.0, 0.0);
 >          size_t total = 0;
 >          foreach(Point3 p; C) {   // enforce that the container 
supports this
 >              c += p; ++total;
 >          }
 >          if (total>  0)
 >              c /= cast(double)(total);
 >          return c;
 >      }

...

 > 2. Secondly, TDPL on page 381 says that foreach iterates over C[], if
 >    C defines the opSlice() function without any arguments.

Although what you describe also seems useful, that heading seems to be 
about ranges and specifically about the three InputRange functions. The 
feature has indeed been implemented recently:

   http://d.puremagic.com/issues/show_bug.cgi?id=5605

 >    However the code above doesn't seem to work and requires me to
 >    explicitly invoke the slice operator myself like
 >      foreach(p; C[]) { ... }
 >    when my data structure clearly defines the following functions.
 >      Point3[] opSlice() { return _cpts[]; }
 >      const (Point3)[] opSlice() const { return _cpts[]; }
 >    Is this a misunderstanding on my part or an unimplemented feature?

But I've just verified that the following works with dmd 2.058:

import std.stdio;

struct Point3
{}

struct MyCollection
{
     Point3[] _cpts;

     Point3[] opSlice() { return _cpts; }  // <-- _cpts[] works too

     const (Point3)[] opSlice() const { return _cpts; }
}

void main()
{
     auto coll = MyCollection();

     foreach (i; coll) {
         // ...
     }
}

Ali



More information about the Digitalmars-d-learn mailing list