digitalmars.D.learn - generic functions
- orgoton (1/1) Apr 27 2007 I've been trying to create a function that would receive a single variab...
- Frits van Bommel (12/13) Apr 27 2007 No, I don't think there's a good way to bypass this. D is a statically
- Chris Nicholson-Sauls (23/43) Apr 27 2007 On the other hand, template functions with a single parameter like this ...
- Frits van Bommel (13/47) Apr 27 2007 Good point. I didn't consider it was perhaps _explicit_ instantiation he...
- Chris Nicholson-Sauls (7/57) Apr 27 2007 I was just working on the assumption that ints/reals were all he was con...
- Frits van Bommel (18/29) Apr 28 2007 That might be a bad idea, since the point of fixed-size integers is that...
I've been trying to create a function that would receive a single variable of any type, like a "abs" function, so that I won't have to code the same function for "real" and "long" var types. What's the most straightforward way to do it? I've seen templates at the D documentation, but those require me to instantiate the function. Is there anyway to bypass this?
Apr 27 2007
orgoton wrote:I've been trying to create a function that would receive a single variable of any type, like a "abs" function, so that I won't have to code the same function for "real" and "long" var types. What's the most straightforward way to do it? I've seen templates at the D documentation, but those require me to instantiate the function. Is there anyway to bypass this?No, I don't think there's a good way to bypass this. D is a statically typed language, so a function needs to know the types of the arguments. --- // Note: doesn't handle byte.min, short.min, int.min and // long.min correctly because their positive values don't // fit into the corresponding type... :( // (This could be fixed by having abs() return the unsigned // variant of those types, but I don't feel like typing // that much) T abs(T)(T val) { return val >= 0 ? val : -val; } ---
Apr 27 2007
Frits van Bommel wrote:orgoton wrote:On the other hand, template functions with a single parameter like this are practically guaranteed IFTI (implicit function template instantiation) so he needn't explicitly instantiate it. I think that may be enough for what he seems to be wanting. So given the function above, 'abs(myvar)' will work just fine. I'm also not sure if there's any way to account for the .min issue without writing the function as a member of a normal template and using a chain of static-if's. template abs (T) { static if (is(T == byte )) alias ubyte R; else static if (is(T == short)) alias ushort R; else static if (is(T == int )) alias uint R; else static if (is(T == long )) alias ulong R; else alias T R; R abs (T val) { static if (is(R : ulong)) const ZERO = 0_UL ; else const ZERO = 0.0_L ; return val >= ZERO ? val : -val; } } Just a quick something, I make no claims toward perfection. If he doesn't mind always returning a ulong, I'm sure he could replace all those static-if's with one 'static if(is(T:long))'. -- Chris Nicholson-SaulsI've been trying to create a function that would receive a single variable of any type, like a "abs" function, so that I won't have to code the same function for "real" and "long" var types. What's the most straightforward way to do it? I've seen templates at the D documentation, but those require me to instantiate the function. Is there anyway to bypass this?No, I don't think there's a good way to bypass this. D is a statically typed language, so a function needs to know the types of the arguments. --- // Note: doesn't handle byte.min, short.min, int.min and // long.min correctly because their positive values don't // fit into the corresponding type... :( // (This could be fixed by having abs() return the unsigned // variant of those types, but I don't feel like typing // that much) T abs(T)(T val) { return val >= 0 ? val : -val; } ---
Apr 27 2007
Chris Nicholson-Sauls wrote:Frits van Bommel wrote:[snip]orgoton wrote:[snip] I've seen templates at the D documentation, but those require me to instantiate the function. Is there anyway to bypass this?Good point. I didn't consider it was perhaps _explicit_ instantiation he had a problem with, instead of instantiation in general.T abs(T)(T val) { return val >= 0 ? val : -val; }On the other hand, template functions with a single parameter like this are practically guaranteed IFTI (implicit function template instantiation) so he needn't explicitly instantiate it. I think that may be enough for what he seems to be wanting. So given the function above, 'abs(myvar)' will work just fine.I'm also not sure if there's any way to account for the .min issue without writing the function as a member of a normal template and using a chain of static-if's. template abs (T) { static if (is(T == byte )) alias ubyte R; else static if (is(T == short)) alias ushort R; else static if (is(T == int )) alias uint R; else static if (is(T == long )) alias ulong R; else alias T R; R abs (T val) { static if (is(R : ulong)) const ZERO = 0_UL ; else const ZERO = 0.0_L ; return val >= ZERO ? val : -val; } } Just a quick something, I make no claims toward perfection. If heGood, because I'm pretty sure that breaks IFTI. You'd have to implement the static ifs in a separate template for the cleanest working code (I think). Oh, and it seems to assume only primitive types are used (in the body). Any particular reason to use a floating-point zero to compare to? Wouldn't a regular int implicitly convert? And also work for user-defined types implementing opCmp & opNeg?doesn't mind always returning a ulong, I'm sure he could replace all those static-if's with one 'static if(is(T:long))'.That should work for all currently implemented types. It'll still break once cent & ucent are implemented though...
Apr 27 2007
Frits van Bommel wrote:Chris Nicholson-Sauls wrote:Y'know... I didn't even think of that. Heh. I told you it was quick.Frits van Bommel wrote:[snip]orgoton wrote:[snip] I've seen templates at the D documentation, but those require me to instantiate the function. Is there anyway to bypass this?Good point. I didn't consider it was perhaps _explicit_ instantiation he had a problem with, instead of instantiation in general.T abs(T)(T val) { return val >= 0 ? val : -val; }On the other hand, template functions with a single parameter like this are practically guaranteed IFTI (implicit function template instantiation) so he needn't explicitly instantiate it. I think that may be enough for what he seems to be wanting. So given the function above, 'abs(myvar)' will work just fine.I'm also not sure if there's any way to account for the .min issue without writing the function as a member of a normal template and using a chain of static-if's. template abs (T) { static if (is(T == byte )) alias ubyte R; else static if (is(T == short)) alias ushort R; else static if (is(T == int )) alias uint R; else static if (is(T == long )) alias ulong R; else alias T R; R abs (T val) { static if (is(R : ulong)) const ZERO = 0_UL ; else const ZERO = 0.0_L ; return val >= ZERO ? val : -val; } } Just a quick something, I make no claims toward perfection. If heGood, because I'm pretty sure that breaks IFTI. You'd have to implement the static ifs in a separate template for the cleanest working code (I think).Oh, and it seems to assume only primitive types are used (in the body). Any particular reason to use a floating-point zero to compare to? Wouldn't a regular int implicitly convert? And also work for user-defined types implementing opCmp & opNeg?I was just working on the assumption that ints/reals were all he was concerned with. A perfect library-appropriate abs() is another creature.Ah, oy. Sometimes I think we should just "implement" cent/ucent as aliases for long/ulong in the meantime. So many things are going to break when they come to fruition as it is. -- Chris Nicholson-Saulsdoesn't mind always returning a ulong, I'm sure he could replace all those static-if's with one 'static if(is(T:long))'.That should work for all currently implemented types. It'll still break once cent & ucent are implemented though...
Apr 27 2007
Chris Nicholson-Sauls wrote:Frits van Bommel wrote:That might be a bad idea, since the point of fixed-size integers is that they are, you know, fixed-size. :P However, I'd like it if the following compiled: --- import std.stdio; void main() { static if(is(cent)) writefln("cent implemented"); else writefln("no cent yet"); } --- (and gave the correct output, of course) Then anybody who cares about this sort of thing would have a way to test for it. And you could use it to define aliases (max_t & umax_t ?) for the largest signed and unsigned integers.Chris Nicholson-Sauls wrote:Ah, oy. Sometimes I think we should just "implement" cent/ucent as aliases for long/ulong in the meantime. So many things are going to break when they come to fruition as it is.doesn't mind always returning a ulong, I'm sure he could replace all those static-if's with one 'static if(is(T:long))'.That should work for all currently implemented types. It'll still break once cent & ucent are implemented though...
Apr 28 2007