opApply and const

Daniel Keep daniel.keep.lists at gmail.com
Sun Dec 9 04:27:04 PST 2007



Bill Baxter wrote:
> I mentioned it in another thread but I just wanted to confirm it.
> Am I right in thinking that if we want to have user types act like
> built-in containers w.r.t iteration in D2 then we need to implement 12
> different versions of opApply?!
> 
> Namely:
> 
> [snip]
> 
> That's a lot of opApply!  I was already mildly annoyed by the four
> needed without const.  But with both const (and invariant) it just seems
> downright silly.
> 
> --bb

There's really no need for the counter versions.  Just solve this the
same way Python did: with a wrapper.  Admittedly, this doesn't seem to
work for more than one argument (foreach appears to dislike tuples for
arguments), but it illustrates the general concept.

	-- Daniel

module enumerate;

import std.stdio;
import std.traits;

struct Enumerate(T)
{
    private
    {
        T source;
        alias ParameterTypeTuple!(typeof(T.opApply))[0] opApply_arg;
        alias ParameterTypeTuple!(opApply_arg) opApply_type;
    }

    int opApply(int delegate(ref size_t, opApply_type) dg)
    {
        int result = 0;
        size_t i = 0;
        foreach( x ; source )
        {
            if( (result=dg(i,x)) != 0 ) break;
            ++i;
        }
        return result;
    }
}

Enumerate!(T) enumerate(T)(T source)
{
    return Enumerate!(T)(source);
}

class Foo
{
    static const words = ["On"[],"a","Sunday,","riding","my","bike"];

    int opApply(int delegate(ref char[]) dg)
    {
        int result = 0;
        foreach( word ; words )
            if( (result=dg(word)) != 0 ) break;
        return result;
    }
}

void main()
{
    foreach( word ; new Foo )
        writef("%s ",word);
    writefln("");

    writefln("");

    foreach( i,word ; enumerate(new Foo) )
        writefln("[%s] %s", i, word);
}



More information about the Digitalmars-d mailing list