<br><div class="gmail_quote">On Sun, Apr 11, 2010 at 04:27, BCS <span dir="ltr"><<a href="mailto:none@anon.com">none@anon.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
Hello Ellery,<div><div></div><div class="h5"><br></div></div>
Oops, that should have been:<div><div></div><div class="h5"><br>
<br>
ret!(T) opDispatch(string s, T...)(T t) { ... }<font color="#888888"><br>
</font><br></div></div></blockquote><div>I couldn't make (string s, T...) to work, though that was the most natural way to do it. <br>Instead, I had to rely on variadic functions:<br><br>struct vector(T, uint N) {<br>
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.<br> static if(N>0 && ("x"==s || "r"==s)) {<br>
if (_arguments.length == 1) {<br> if (_arguments[0] == typeid(T)) {<br> v_[0] = *cast(T*)_argptr;<br> }<br> else {<br> throw new Exception("Bad argument for vector.x, should be of type " ~ T.stringof);<br>
}<br> }<br> return v_[0];<br> }<br> static if(N>1 && ("y"==s || "g"==s)) return v_[1]; // TODO: the same for y,z and w...<br> static if(N>2 && ("z"==s || "b"==s)) return v_[2];<br>
static if(N>3 && ("w"==s || "a"==s)) return v_[3];<br><br> static assert("boom!");<br> }<br><br> T[n] v_;<br>}<br><br>void main() {<br> vector!(int, 3) v;<br> writeln(v.x); // 0<br>
v.x = 1;<br> writeln(v.x); // 1<br>}<br><br><br>What's even more grand, is when you use opDispatch to generate the function for you. In this case, you can get swizzling (sp?):<br><br>// first, a helper template, needed to get a static foreach. Useful everywhere, this template.<br>
// alias it self to TypeTuple!(T,T,T,...) with n Ts<br>template TypeNuple(T, size_t n) {<br> static if(n == 0) {<br> alias TypeTuple!() TypeNuple;<br> }<br> else {<br> alias TypeTuple!(T,TypeNuple!(T, n-1)) TypeNuple;<br>
}<br>}<br><br>// change: Vector with a 'V'<br>// change: opDispatch(string s) if (s.length >1)<br>struct Vector(T, uint N) {<br> auto ref opDispatch(string s)(...) if (s.length == 1) {<br> static if(N>0 && ("x"==s || "r"==s)) return v_[0];<br>
static if(N>1 && ("y"==s || "g"==s)) return v_[1];<br> static if(N>2 && ("z"==s || "b"==s)) return v_[2];<br> static if(N>3 && ("w"==s || "a"==s)) return v_[3];<br>
<br> static assert("boom!");<br> }<br><br> T[s.length] opDispatch(string s)() if (s.length > 1) { // s.length> 1: will construct the value from the first opDispatch<br> T[s.length] result;<br>
alias TypeNuple!(T, s.length) TN; // to get a compile-time foreach<br> foreach(i, Type; TN) {<br> 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<br>
}<br> return result;<br> }<br><br> private:<br> T[N] v_;<br>}<br><br>// and then, a handy helper function to create a Vector:<br>// need import std.traits;<br>Vector!(CommonType!T, T.length) vector(T...)(T args) if (is(CommonType!T))<br>
{<br> return Vector!(CommonType!T, T.length)([args]); // args is a tuple, so [args] dumps it into an array<br>}<br><br>usage:<br><br>void main() {<br> auto v = vector(1,2,3); // deduced by the compiler to be a Vector!(int, 3)<br>
auto v2 = vector(1.2,2,3,4); // deduced by the compiler to be Vector!(double, 4)<br><br>// and then, swizzling<br> writeln(v.yzx); // "231"<br> writeln(v.xxxx); // "1111"<br><br>}<br><br></div></div>