digitalmars.D - opDispatch is grand!
- so (18/19) Apr 10 2010 struct vector(T, uint N) {
- so (16/33) Apr 10 2010 Because i made a mistake!
- Ellery Newcomer (24/37) Apr 10 2010 Can you get
- BCS (6/52) Apr 10 2010 I think you might be able to do:
- Ellery Newcomer (2/6) Apr 10 2010 I don't think so; it looks like dmd rewrites invocations as opDispatch!(...
- BCS (5/18) Apr 10 2010 Oops, that should have been:
- Philippe Sigaud (85/89) Apr 11 2010 way to do it.
struct vector(T, uint N) {
auto opDispatch(string s) const {
static if(N>0 && ("x"==s || "r"==s)) return v_[0];
static if(N>1 && ("y"==s || "g"==s)) return v_[0];
static if(N>2 && ("z"==s || "b"==s)) return v_[0];
static if(N>3 && ("w"==s || "a"==s)) return v_[0];
static assert("boom!");
}
private:
T[N] v_;
}
No unions, clean and all!
Then why do we need properties?
When i am sick, i try distract myself, this is one of those times, so just
ignore me if it doesn't make sense :)
Thanks!
--
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Apr 10 2010
Because i made a mistake!
struct vector(T, uint N) {
auto opDispatch(string s) const {
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!");
}
private:
T[N] v_;
}
Better...
On Sun, 11 Apr 2010 02:49:14 +0400, so <so so.do> wrote:
struct vector(T, uint N) {
auto opDispatch(string s) const {
static if(N>0 && ("x"==s || "r"==s)) return v_[0];
static if(N>1 && ("y"==s || "g"==s)) return v_[0];
static if(N>2 && ("z"==s || "b"==s)) return v_[0];
static if(N>3 && ("w"==s || "a"==s)) return v_[0];
static assert("boom!");
}
private:
T[N] v_;
}
No unions, clean and all!
Then why do we need properties?
When i am sick, i try distract myself, this is one of those times, so
just ignore me if it doesn't make sense :)
Thanks!
--
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Apr 10 2010
On 04/10/2010 05:49 PM, so wrote:
struct vector(T, uint N) {
auto opDispatch(string s) const {
static if(N>0 && ("x"==s || "r"==s)) return v_[0];
static if(N>1 && ("y"==s || "g"==s)) return v_[0];
static if(N>2 && ("z"==s || "b"==s)) return v_[0];
static if(N>3 && ("w"==s || "a"==s)) return v_[0];
static assert("boom!");
}
private:
T[N] v_;
}
No unions, clean and all!
Then why do we need properties?
Can you get
vector!(int,3) v;
v.x = 1;
to work?
The closest I can get is
struct vector(T, uint N) {
ref T opDispatch(string s )() {
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!");
}
private:
T[N] v_;
}
..
vector!(int, 3) v;
v.x() = 1;
when DMD sees
v.x = 1;
it tries to rewrite it as v.x(1);
And I can't figure out how to overload opDispatch
Apr 10 2010
Hello Ellery,On 04/10/2010 05:49 PM, so wrote:I think you might be able to do: ret!(T) opDispatch(string s, T)(T t) { ... } and then switch internally based on T. -- ... <IXOYE><struct vector(T, uint N) { auto opDispatch(string s) const { static if(N>0 && ("x"==s || "r"==s)) return v_[0]; static if(N>1 && ("y"==s || "g"==s)) return v_[0]; static if(N>2 && ("z"==s || "b"==s)) return v_[0]; static if(N>3 && ("w"==s || "a"==s)) return v_[0]; static assert("boom!"); } private: T[N] v_; } No unions, clean and all! Then why do we need properties?Can you get vector!(int,3) v; v.x = 1; to work? The closest I can get is struct vector(T, uint N) { ref T opDispatch(string s )() { 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!"); } private: T[N] v_; } .. vector!(int, 3) v; v.x() = 1; when DMD sees v.x = 1; it tries to rewrite it as v.x(1); And I can't figure out how to overload opDispatch
Apr 10 2010
On 04/10/2010 09:04 PM, BCS wrote:
Hello Ellery,
I think you might be able to do:
ret!(T) opDispatch(string s, T)(T t) { ... }
and then switch internally based on T.
I don't think so; it looks like dmd rewrites invocations as opDispatch!("x")
Apr 10 2010
Hello Ellery,On 04/10/2010 09:04 PM, BCS wrote:Oops, that should have been: ret!(T) opDispatch(string s, T...)(T t) { ... } -- ... <IXOYE><Hello Ellery, I think you might be able to do: ret!(T) opDispatch(string s, T)(T t) { ... } and then switch internally based on T.I don't think so; it looks like dmd rewrites invocations as opDispatch!("x")
Apr 10 2010
On Sun, Apr 11, 2010 at 04:27, BCS <none 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"
}
Apr 11 2010









so <so so.do> 