templates

bearophile bearophileHUGS at lycos.com
Mon Apr 19 14:20:21 PDT 2010


Steven Schveighoffer:

> What I had in mind was:
> 
> struct S
> {
>    int foo(int x) { return x * 2; }
> }
> 
> struct S2
> {
>    int foo(int x) { return x + 2; }
> }
> 
> void main()
> {
>     S s1;
>     S2 s2;
> 
>     IW[] ws;
> 
>     ws ~= makeW(s1);
>     ws ~= makeW(s2);
> 
>     assert(ws[0].foo(3) == 6);
>     assert(ws[1].foo(3) == 5);
> }
> 
> does this help?

A possible solution, this code is just an idea that needs improvements, it's not generic:

struct S1 {
   int foo(int x) { return x * 2; }
}

struct S2 {
   int foo(int x) { return x + 2; }
}

enum TypeTag { TS1, TS2 }

struct Wrapper {
    TypeTag tag;

    union {
        S1 s1;
        S2 s2;
    }

    int foo(int x) {
        final switch(this.tag) {
            case TypeTag.TS1: return s1.foo(x);
            case TypeTag.TS2: return s2.foo(x);
       }
    }
}

Wrapper makeW(T)(T s) if (is(T == S1) || is(T == S2)) {
    static if (is(T == S1)) {
        Wrapper result = Wrapper(TypeTag.TS1);
        result.s1 = s;
        return result;
    } else static if (is(T == S2)) {
        Wrapper result = Wrapper(TypeTag.TS2);
        result.s2 = s;
        return result;
    } else
        assert(0);
}

void main() {
    S1 s1;
    S2 s2;

    Wrapper[] ws;
    ws ~= makeW(s1);
    ws ~= makeW(s2);

    assert(ws[0].foo(3) == 6);
    assert(ws[1].foo(3) == 5);
}


There are several other ways to solve this problem. This version is a bit nicer because it contains no pointer casts.
Languages that have a tagged union (like Cyclone) need quite less code here, but probably D2 can be used to remove some of that code duplication.

Bye,
bearophile


More information about the Digitalmars-d-learn mailing list