opDispatch is grand!

Philippe Sigaud philippe.sigaud at gmail.com
Sun Apr 11 12:19:37 PDT 2010


On Sun, Apr 11, 2010 at 04:27, BCS <none at anon.com> wrote:

> Hello Ellery,
>
> Oops, that should have been:
>
>
> ret!(T) opDispatch(string s, T...)(T t) { ... }
>
> I couldn't make (string s, T...) to work, though that was the most natural
way to do it.
Instead, I had to rely on variadic functions:

struct vector(T, uint N) {
    auto ref opDispatch(string s)(...) if (s.length == 1) { // I don't think
the auto ref is still necessary. It appeared during iterations on this.
        static if(N>0 && ("x"==s || "r"==s)) {
            if (_arguments.length == 1) {
                if (_arguments[0] == typeid(T)) {
                    v_[0] = *cast(T*)_argptr;
                }
                else {
                    throw new Exception("Bad argument for vector.x, should
be of type " ~ T.stringof);
                }
            }
            return v_[0];
       }
       static if(N>1 && ("y"==s || "g"==s)) return v_[1]; // TODO: the same
for y,z and w...
       static if(N>2 && ("z"==s || "b"==s)) return v_[2];
       static if(N>3 && ("w"==s || "a"==s)) return v_[3];

       static assert("boom!");
    }

  T[n] v_;
}

void main() {
   vector!(int, 3) v;
   writeln(v.x); //  0
   v.x = 1;
   writeln(v.x); // 1
}


What's even more grand, is when you use opDispatch to generate the function
for you. In this case, you can get swizzling (sp?):

// first, a helper template, needed to get a static foreach. Useful
everywhere, this template.
// alias it self to TypeTuple!(T,T,T,...) with n Ts
template TypeNuple(T, size_t n) {
    static if(n == 0) {
        alias TypeTuple!() TypeNuple;
    }
    else {
        alias TypeTuple!(T,TypeNuple!(T, n-1)) TypeNuple;
    }
}

// change: Vector with a 'V'
// change: opDispatch(string s) if (s.length >1)
struct Vector(T, uint N) {
    auto ref opDispatch(string s)(...) if (s.length == 1) {
       static if(N>0 && ("x"==s || "r"==s)) return v_[0];
       static if(N>1 && ("y"==s || "g"==s)) return v_[1];
       static if(N>2 && ("z"==s || "b"==s)) return v_[2];
       static if(N>3 && ("w"==s || "a"==s)) return v_[3];

       static assert("boom!");
    }

    T[s.length] opDispatch(string s)() if (s.length > 1) { // s.length> 1:
will construct the value from the first opDispatch
        T[s.length] result;
        alias TypeNuple!(T, s.length) TN; // to get a compile-time foreach
        foreach(i, Type; TN) {
            result[i] = this.opDispatch!(s[i..i+1])(); // that way, i is a
CT index. I use s[i..i+1] to get a string
        }
        return result;
    }

    private:
    T[N] v_;
}

// and then, a handy helper function to create a Vector:
// need import std.traits;
Vector!(CommonType!T, T.length) vector(T...)(T args) if (is(CommonType!T))
{
    return Vector!(CommonType!T, T.length)([args]); // args is a tuple, so
[args] dumps it into an array
}

usage:

void main() {
    auto v = vector(1,2,3); // deduced by the compiler to be a Vector!(int,
3)
   auto v2 = vector(1.2,2,3,4); // deduced by the compiler to be
Vector!(double, 4)

// and then, swizzling
   writeln(v.yzx); // "231"
  writeln(v.xxxx); // "1111"

}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20100411/e44bb633/attachment.html>


More information about the Digitalmars-d mailing list