digitalmars.D.learn - Questions about opAssign alternate and template quality
- nobody (56/56) Aug 10 2006 I wanted to try out D's template system so I decided to define data stru...
- Oskar Linde (61/88) Aug 10 2006 I don't know of any elegant alternative. I also find it very unfortunate...
- nobody (5/50) Aug 11 2006 Thanks for the great post! Your pixAssign function is a great example an...
I wanted to try out D's template system so I decided to define data structures that represent all the permutations of RGB, HLS, RGBA and HLSA. I decided to convert between the various types by overriding opAssign under the mistaken impression that D supported it. Impressive when you do the math: 3! + 3! + 4! + 4! = 60 types (3! + 3! + 4! + 4!)^2 = 3600 opAssigns So my first question is whether anyone has an elegant alternative to using opAssign? My second question is mostly an open invitation to make suggestions for improving my template writing style. In particular I am suspicious that there is a way to take better advantage of templates and not write out all 60 permutations. So here is the actual code. I only included the RGB permutations to keep it as short as possible. union PixArray { PixBGR[] bgr; PixBRG[] brg; PixGBR[] gbr; PixGRB[] grb; PixRBG[] rbg; PixRGB[] rgb; } template PixBGR_Perms_opAssignBGR(T,U) { T opAssign(U that) { ubyte tempB = that.b; ubyte tempG = that.g; ubyte tempR = that.r; this.b = tempB; this.g = tempG; this.r = tempR; return *this; } } template PixBGR_Perms(T) { alias b blue; alias g green; alias r red; // opAssign defined for all perms mixin PixBGR_Perms_opAssignBGR!(T,PixBGR); mixin PixBGR_Perms_opAssignBGR!(T,PixBRG); mixin PixBGR_Perms_opAssignBGR!(T,PixGBR); mixin PixBGR_Perms_opAssignBGR!(T,PixGRB); mixin PixBGR_Perms_opAssignBGR!(T,PixRBG); mixin PixBGR_Perms_opAssignBGR!(T,PixRGB); } align(1) { struct PixBGR { ubyte b; ubyte g; ubyte r; mixin PixBGR_Perms!(PixBGR); } struct PixBRG { ubyte b; ubyte r; ubyte g; mixin PixBGR_Perms!(PixBRG); } struct PixGBR { ubyte g; ubyte b; ubyte r; mixin PixBGR_Perms!(PixGBR); } struct PixGRB { ubyte g; ubyte r; ubyte b; mixin PixBGR_Perms!(PixGRB); } struct PixRBG { ubyte r; ubyte b; ubyte g; mixin PixBGR_Perms!(PixRBG); } struct PixRGB { ubyte r; ubyte g; ubyte b; mixin PixBGR_Perms!(PixRGB); } }
Aug 10 2006
nobody wrote:I wanted to try out D's template system so I decided to define data structures that represent all the permutations of RGB, HLS, RGBA and HLSA. I decided to convert between the various types by overriding opAssign under the mistaken impression that D supported it. Impressive when you do the math: 3! + 3! + 4! + 4! = 60 types (3! + 3! + 4! + 4!)^2 = 3600 opAssigns So my first question is whether anyone has an elegant alternative to using opAssign?I don't know of any elegant alternative. I also find it very unfortunate that opAssign isn't overloadable for structs.My second question is mostly an open invitation to make suggestions for improving my template writing style. In particular I am suspicious that there is a way to take better advantage of templates and not write out all 60 permutations. So here is the actual code. I only included the RGB permutations to keep it as short as possible.Implicit function template instantiation and some static ifs can help you. Unfortunately, IFTI isn't yet implemented for member functions, but you can make a free function like: void pixAssign(A,B)(out A A, in B b) { static if (is(a.a) && is(b.a)) { // Alpha a.a = b.a; } else static if(is(a.a)) { a.a = typeof(a.a).max; } static if (is(a.r) && is(b.r)) { // RGB->RGB auto r = b.r; auto g = b.g; auto b = b.b; a.r = r; a.g = g; a.b = b; } else static if (is(a.h) && is(b.h)) { // HLS -> HLS auto h = b.h; auto l = b.l; auto s = b.s; a.h = h; a.l = l; a.s = s; } else static if(is(a.r)) { // HLS -> RGB assert(0,"not implemented."); } else static if(is(b.r)) { // RGB -> HLS assert(0,"not implemented."); } } Which should take care of all 3600 combinations of opAssign. is(x.y) is there just to check for the existence of a field y in x. Which can be called: pixAssign(dst,src); You can also add the following to your PixColor structs: void opAssign(B)(B b) { pixAssign(*this,b); } Bur, until IFTI is implemented for member functions, you would have to call it: c1.opAssign!(typeof(c2))(c2); And one can always hope, that in the future it will be: c1 = c2;align(1) { struct PixBGR { ubyte b; ubyte g; ubyte r; mixin PixBGR_Perms!(PixBGR); } struct PixBRG { ubyte b; ubyte r; ubyte g; mixin PixBGR_Perms!(PixBRG); } struct PixGBR { ubyte g; ubyte b; ubyte r; mixin PixBGR_Perms!(PixGBR); } struct PixGRB { ubyte g; ubyte r; ubyte b; mixin PixBGR_Perms!(PixGRB); } struct PixRBG { ubyte r; ubyte b; ubyte g; mixin PixBGR_Perms!(PixRBG); } struct PixRGB { ubyte r; ubyte g; ubyte b; mixin PixBGR_Perms!(PixRGB); } }You can also make a template that automatically defines your Pix??? types, but I am not sure it is worth it. alias Pix!(R,G,B) PixRGB; alias Pix!(R,G,B,A) PixRGBA; alias Pix!(A,R,G,B) PixARGB; alias Pix!(H,L,S) PixHLS; alias Pix!(B,G,R) PixBGR; alias Pix!(R,B,G) PixRBG; alias Pix!(B,R,G) PixBRG; ... /Oskar
Aug 10 2006
Oskar Linde wrote:Thanks for the great post! Your pixAssign function is a great example and helped me better understand static if, is and auto. It might take awhile before I can see why there would be trouble with trying to use a mixin to avoid paramatized calls to opAssign.My second question is mostly an open invitation to make suggestions for improving my template writing style. In particular I am suspicious that there is a way to take better advantage of templates and not write out all 60 permutations. So here is the actual code. I only included the RGB permutations to keep it as short as possible.Implicit function template instantiation and some static ifs can help you. Unfortunately, IFTI isn't yet implemented for member functions, but you can make a free function like: void pixAssign(A,B)(out A A, in B b) { static if (is(a.a) && is(b.a)) { // Alpha a.a = b.a; } else static if(is(a.a)) { a.a = typeof(a.a).max; } static if (is(a.r) && is(b.r)) { // RGB->RGB auto r = b.r; auto g = b.g; auto b = b.b; a.r = r; a.g = g; a.b = b; } else static if (is(a.h) && is(b.h)) { // HLS -> HLS auto h = b.h; auto l = b.l; auto s = b.s; a.h = h; a.l = l; a.s = s; } else static if(is(a.r)) { // HLS -> RGB assert(0,"not implemented."); } else static if(is(b.r)) { // RGB -> HLS assert(0,"not implemented."); } } Which should take care of all 3600 combinations of opAssign. is(x.y) is there just to check for the existence of a field y in x.
Aug 11 2006