On Sun, Apr 11, 2010 at 04:27, BCS <n...@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" }