Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Copyable stack delegates (with writefln)

Part of DelegateCategory

Description

Some examples of how to copy a stack's local variables. Useful if you don't want to modify the original local variables, or if you want to return a stack delegates.

Example

/* This shows two different ways of creating a pseudo-copied stack delegate.
 *
 * The struct method is more efficient.  However, it is a bit harder to write & understand.
 * Also, it requires that you build a delegate by hand using a union, and that may not be
 * portable across all platforms or compilers.
 *
 * The class method is easier to understand and should be totally portable.  However,
 * it is less efficient because of the overhead inherent in a class.
 */

import std.stdio;

int RunDelegate(int delegate() d, int count) {
    assert(count > 0);

    int ret;
    for(int i=0; i<count; i++) {
        ret = d();
//        writefln("RunDelegate: cycle %d of %d returned %d\n", i+1,count,ret);
    }
    return ret;
}


int main() {
    int delegate() d1 = getS(2);
    int delegate() d2 = getS(3);
    int delegate() d3 = getC(2);
    int delegate() d4 = getC(3);

    writefln("main: RunDelegate(d1,4) returned %d", RunDelegate(d1,4));
    writefln("main: RunDelegate(d1,4) returned %d", RunDelegate(d1,4));

    writefln("main: RunDelegate(d2,4) returned %d", RunDelegate(d2,4));
    writefln("main: RunDelegate(d2,4) returned %d", RunDelegate(d2,4));

    writefln("main: RunDelegate(d3,4) returned %d", RunDelegate(d3,4));
    writefln("main: RunDelegate(d3,4) returned %d", RunDelegate(d3,4));

    writefln("main: RunDelegate(d4,4) returned %d", RunDelegate(d4,4));
    writefln("main: RunDelegate(d4,4) returned %d", RunDelegate(d4,4));

    return 0;
}

    /* both getS() and getC() return stack-copy style delegates.  In each case,
     * the delegate stores the argument to the function, and a counter.  Each time
     * that the delegate is called, the counter is multiplied by the argument, and
     * the result is returned.
     *
     * The end result is that, if you create a delegate with an argument of x and you
     * call it y times, then the y-th time it will return
     *     x^y
     */

    /* getS() returns the delegate using the struct method;
     * getC() returns the delegate using the class method.
     */

struct GetS_Data {
    int base;
    int counter;
};


union delegate_union {
    int delegate() dg;
    struct {
        void *ptr;
        int function(void*) func;
    };
};


int delegate() getS(int base) {
    GetS_Data *data = new GetS_Data[1];
    data.base = base;
    data.counter = 1;

    delegate_union u;
    u.func = function int(void *arg) {
             GetS_Data *data = cast(GetS_Data*)arg;
             data.counter *= data.base;
             return data.counter;
           };
    u.ptr = data;

    return u.dg;
}


class GetC_Data {
    int counter;
    int base;

    this(int base) {
        this.base = base;
        this.counter = 1;
    }

    int func() {
        counter *= base;
        return counter;
    }
}


int delegate() getC(int base) {
    GetC_Data data = new GetC_Data(base);
    return &data.func;
}

Source

Original contribution by Russ Lewis. Changed based on suggestions by Blandger.

Link http://www.dsource.org/tutorials/index.php?show_example=112
Edited by jcc7
Date/Time Thu Jul 29, 2004 9:59 pm