Supporting and signature-checking all foreach variations

Dmitry Olshansky dmitry.olsh at gmail.com
Sat Feb 25 12:58:32 PST 2012


On 25.02.2012 20:25, 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;
>      }
>
> I want to have the most generally-applicable version of this functionality
> (for const/immutable/etc containers supporting foreach in various ways),
> ideally without needing to write multiple versions of this function.
>
> 1. Since support for foreach can be added in many ways (with
>    ref/non-ref/const variants), I wanted to check if there was any
>    signature constraint that could check if the container supports foreach
>    as above. I looked into the "compiles" traits, but that doesn't work for
>    statements.
>
>    For an opAssign version, I had tried
>      if (is(typeof(C.opApply(delegate(const ref Point3) { return 1;}))))
>    but this is unelegant because the container's opApply could have instead
>    supplied delegate(Point3) or delegate(ref Point3) (although the latter
>    would require me to not use a "const" on the parameter declaration).
>
> 2. Secondly, TDPL on page 381 says that foreach iterates over C[], if
>    C defines the opSlice() function without any arguments.
>    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?

It's supposed to work.
I think it's just not implemented yet.

>
> 3. A more general question: Is there any by any chance a way to avoid the
>    redundancy above of defining two opSlice() functions (or two opAssign()
>    functions if I went that route -- one for const and another for ref)?
>    I suspect that the answer is no, but I just wanted to verify.


-- 
Dmitry Olshansky


More information about the Digitalmars-d-learn mailing list