www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Multiple Specialization?

reply Xinok <xnknet gmail.com> writes:
I'm not sure what else you could call this...

My idea for multiple specialization is to be able to associate multiple types
with a single template. Take for example:

template temp(T){ }
template temp(T : int, T : long){ } // Specialized Template
It would use the specialized template if T == int OR T == short

I have two designs for this, the first you see above. Because the order of
template arguments is important, all types must come in succession:
template temp(T1, T2 : int, T2 : long, T3){ } // OK
template temp(T1, T2 : int, T3, T2 : long){ } // Error - T2 is not in succession
This is important, because the compiler can't be sure if T2 or T3 comes first:
(T1, T2, T3) or (T1, T3, T2)

My second design is to use braces:
template temp(T1, T2 : {int, long}, T3){ }

I also think you could use tuples somehow, but I have no idea how you could
write that. But take for example:
template tuple(T...){ alias T tuple; }
template temp(T : tuple!(int, long)){ }

I think tuples would work best because you can define aliases for them, where
as you can't define an alias for the two other designs:
alias tuple!(byte, short, int long) intset;
template temp(T1 : intset, T2 : intset){ }


What could this be used for? Suppose you wanted to make a specialized template
for all int types? Or float types? Or char types? You would have to duplicate
the template multiple times, especially if you have two or more types:
template temp(T1 : {byte, short, int, long}, T2 : {byte, short, int long}){ }
This would normally require you to define 16 specialized templates.
Dec 22 2006
parent reply Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Xinok wrote:
 I'm not sure what else you could call this...
 
 My idea for multiple specialization is to be able to associate multiple types
 with a single template. Take for example:
 
 template temp(T){ }
 template temp(T : int, T : long){ } // Specialized Template
 It would use the specialized template if T == int OR T == short
 
 I have two designs for this, the first you see above. Because the order of
 template arguments is important, all types must come in succession:
 template temp(T1, T2 : int, T2 : long, T3){ } // OK
 template temp(T1, T2 : int, T3, T2 : long){ } // Error - T2 is not in
succession
 This is important, because the compiler can't be sure if T2 or T3 comes first:
 (T1, T2, T3) or (T1, T3, T2)
 
 My second design is to use braces:
 template temp(T1, T2 : {int, long}, T3){ }
 
 I also think you could use tuples somehow, but I have no idea how you could
 write that. But take for example:
 template tuple(T...){ alias T tuple; }
 template temp(T : tuple!(int, long)){ }

Or even just: template temp(T : (int, long)) { }
 
 I think tuples would work best because you can define aliases for them, where
 as you can't define an alias for the two other designs:
 alias tuple!(byte, short, int long) intset;
 template temp(T1 : intset, T2 : intset){ }
 
 
 What could this be used for? Suppose you wanted to make a specialized template
 for all int types? Or float types? Or char types? You would have to duplicate
 the template multiple times, especially if you have two or more types:
 template temp(T1 : {byte, short, int, long}, T2 : {byte, short, int long}){ }
 This would normally require you to define 16 specialized templates.

Or one template with a long static if at the beginning, which can be annoying for, say, template functions. Its an interesting idea at the least -- but I'm not sure what it might take in the compiler. -- Chris Nicholson-Sauls
Dec 22 2006
parent reply Bill Baxter <wbaxter gmail.com> writes:
Chris Nicholson-Sauls wrote:
 Xinok wrote:
 
 I'm not sure what else you could call this...

 My idea for multiple specialization is to be able to associate 
 multiple types
 with a single template. Take for example:

 template temp(T){ }
 template temp(T : int, T : long){ } // Specialized Template
 It would use the specialized template if T == int OR T == short


I agree with Chris that grouping the types seems like a better idea. Repeating T is asking for trouble. (T : {a, b}) or somesuch. Or maybe multiple colons (T :a:b)
 What could this be used for? Suppose you wanted to make a specialized 
 template
 for all int types? Or float types? Or char types? You would have to 
 duplicate
 the template multiple times, especially if you have two or more types:
 template temp(T1 : {byte, short, int, long}, T2 : {byte, short, int 
 long}){ }
 This would normally require you to define 16 specialized templates.

Or one template with a long static if at the beginning, which can be annoying for, say, template functions. Its an interesting idea at the least -- but I'm not sure what it might take in the compiler.

Yeh, static if(is(...)) is the way I'd do this now. That also allows you to accept "any type implicitly convertable to T" which covers a lot of real-world cases. For the most part you don't care if it's one of 16 specific types, you care if it can be assigned to an 'int' or if an int can be assigned to it. Personally, I have yet to use specialization, because of it's annoying "feature" of disabling IFTI. (At least that's the way it seemed the last time I tried it -- correct me if I'm wrong there) I would love for it to become usable. But right now static if is more flexible and powerful. I agree that it would be nice if the same power were available via the specialization syntax. --bb
Dec 22 2006
parent reply Xinok <xnknet gmail.com> writes:
I don't like the idea of using parenthesis or braces.
I'm trying to create a design which wouldn't require adding a new syntax to D.

I really like the idea of using tuples, that is if multiple specialization were
to
be added to D.
Tuples are already a part of D, so it wouldn't require adding anything new.
Also, tuples have a few features which could come in handy with multiple
specialization.

The first feature I already mentioned, you can define aliases for tuples.
alias tuple!(byte, short, int, long) intset;
template temp(T : intset){ }

Second, the splitting operator:
template temp(T : intset[1..length]){ } // short, int, long

Third, tuples can take both types and constants, so they could be used to
specialize variables too.
template temp(int V : tuple!(15, 30, 45)){ }
Dec 22 2006
parent reply Paul Findlay <r.lph50+d gmail.com> writes:
Xinok wrote:
 I don't like the idea of using parenthesis or braces.
 I'm trying to create a design which wouldn't require adding a new syntax to D.
 
 I really like the idea of using tuples, that is if multiple specialization
were to
 be added to D.

thought this would be a more natural step for D to get some pattern matching on template arguments. So from code I have seen in minid (which brilliant): public int write(T)(MDState s) { MDFile i = cast(MDFile)s.getInstanceParam(0, this); T val; static if(is(T == ubyte) || is(T == ushort) || is(T == int)) val = s.getIntParam(1); else static if(is(T == float)) val = s.getFloatParam(1); else static if(is(T == char) || is(T == wchar) || is(T == dchar)) val = s.getCharParam(1); //.. snip return 0; } a static switch version: public int write(T)(MDState s) { MDFile i = cast(MDFile)s.getInstanceParam(0, this); T val; static switch(T) { case(ubyte): case(ushort): case(int): val = s.getIntParam(1); break; case(float): val = s.getFloatParam(1); break; case(char): case(wchar): case(dchar): val = s.getCharParam(1); break; } //.. snip return 0; } and I imagined having static switch and case been able to handle type tuples if for example the function prototype was public int write(T...)(MDState s) // no example because I am lazy Does this make sense? - Paul
Dec 23 2006
parent BCS <BCS pathilink.com> writes:
Paul Findlay wrote:
 This is an idea I had one walk.. using something like a static switch.

 a static switch version:


 public int write(T)(MDState s)
 {
     MDFile i = cast(MDFile)s.getInstanceParam(0, this);

     T val;

     static switch(T) {
     case(ubyte): case(ushort): case(int):
         val = s.getIntParam(1);
         break;
     case(float):
         val = s.getFloatParam(1);
         break;
     case(char): case(wchar): case(dchar):
         val = s.getCharParam(1);
         break;
     }
 //.. snip

     return 0;
 }

 and I imagined having static switch and case been able to handle type
 tuples if for example the function prototype was

 public int write(T...)(MDState s)
 // no example because I am lazy

 Does this make sense?

  - Paul

Yes I was thinking of posting about the same concept my self. (I second the ides)
Dec 23 2006