www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - MIN MAX problem

reply freeagle <dalibor.free gmail.com> writes:
Hey all,

from what I know, there is (currently?) no way of implementing min/max 
template functions that could dynamically change return type depending 
on the result of comparison. I think that this problem can be "solved" 
easily. When used in C++, there is no problem with the return type as 
min/max are coded as macros. But there is always probability that the 
result of the min/max will be cast into appropriate type, because 
variables cant be both float and int at the same time, for example.
That means, when you write in C++

float f = 1.0f, result;
int a = 2;
result = MAX(f, a);

the result is cast to float when assignment to the variable is being 
done. This means you always know of what type you want the result to be.
I say we could move the casting into the function itself, like this:

T max(T, U)(T arg1, U arg2)
{
	return cast(T) (arg1 > arg2 ? arg1 : arg2);
}

and make it a standard that the type of the first argument will always 
be the returning type of the min/max function.

Just a thought

freeagle
Mar 12 2007
next sibling parent reply torhu <fake address.dude> writes:
freeagle wrote:
 the result is cast to float when assignment to the variable is being 
 done. This means you always know of what type you want the result to be.
 I say we could move the casting into the function itself, like this:
 
 T max(T, U)(T arg1, U arg2)
 {
 	return cast(T) (arg1 > arg2 ? arg1 : arg2);
 }
 
 and make it a standard that the type of the first argument will always 
 be the returning type of the min/max function.

You can use typeof to get the common type, like this: typeof(T + U) max(T, U)(T arg1, U arg2) { return arg1 > arg2 ? arg1 : arg2; }
Mar 13 2007
next sibling parent reply freeagle <dalibor.free gmail.com> writes:
torhu wrote:
 freeagle wrote:
 the result is cast to float when assignment to the variable is being 
 done. This means you always know of what type you want the result to be.
 I say we could move the casting into the function itself, like this:

 T max(T, U)(T arg1, U arg2)
 {
     return cast(T) (arg1 > arg2 ? arg1 : arg2);
 }

 and make it a standard that the type of the first argument will always 
 be the returning type of the min/max function.

You can use typeof to get the common type, like this: typeof(T + U) max(T, U)(T arg1, U arg2) { return arg1 > arg2 ? arg1 : arg2; }

havent seen in the docs something like type adding ?! anyway, my guess is that the typeof(T + U) expresion always return the the same type for each couple of types. so float + int would always return float? what if you want it to return int?
Mar 12 2007
parent BCS <ao pathlink.com> writes:
Reply to freeagle,

 torhu wrote:
 
 freeagle wrote:
 
 the result is cast to float when assignment to the variable is being
 done. This means you always know of what type you want the result to
 be. I say we could move the casting into the function itself, like
 this:
 
 T max(T, U)(T arg1, U arg2)
 {
 return cast(T) (arg1 > arg2 ? arg1 : arg2);
 }
 and make it a standard that the type of the first argument will
 always be the returning type of the min/max function.
 

typeof(T + U) max(T, U)(T arg1, U arg2) { return arg1 > arg2 ? arg1 : arg2; }

is that the typeof(T + U) expresion always return the the same type for each couple of types. so float + int would always return float? what if you want it to return int?

The type of every function is fixed at compile time, It can't return a float sometimes and an int others.
Mar 13 2007
prev sibling parent reply Walter Bright <newshound digitalmars.com> writes:
torhu wrote:
 You can use typeof to get the common type, like this:
 
 typeof(T + U) max(T, U)(T arg1, U arg2)
 {
         return arg1 > arg2 ? arg1 : arg2;
 }

The + isn't always defined, so you can use: typeof(true ? cast(T)0 : cast(U)0) max(T, U)(T x1, U x2) { return x1 > x2 ? x1 : x2; }
Mar 13 2007
next sibling parent reply freeagle <dalibor.free gmail.com> writes:
Walter Bright wrote:
 torhu wrote:
 You can use typeof to get the common type, like this:

 typeof(T + U) max(T, U)(T arg1, U arg2)
 {
         return arg1 > arg2 ? arg1 : arg2;
 }

The + isn't always defined, so you can use: typeof(true ? cast(T)0 : cast(U)0) max(T, U)(T x1, U x2) { return x1 > x2 ? x1 : x2; }

typeof(true ? cast(T)0 : cast(U)0) And, i think this wont work for classes that overload the >,< etc operator, as you can't do cast(class)0, can you?
Mar 12 2007
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
freeagle wrote:
 Walter Bright wrote:
 torhu wrote:
 You can use typeof to get the common type, like this:

 typeof(T + U) max(T, U)(T arg1, U arg2)
 {
         return arg1 > arg2 ? arg1 : arg2;
 }

The + isn't always defined, so you can use: typeof(true ? cast(T)0 : cast(U)0) max(T, U)(T x1, U x2) { return x1 > x2 ? x1 : x2; }

typeof(true ? cast(T)0 : cast(U)0) And, i think this wont work for classes that overload the >,< etc operator, as you can't do cast(class)0, can you?

In the archives somewhere, there is a long thread discussing an implementation of min (or max; can't remember). From what I do remember, it basically boiled down to "good grief this is actually really hard once you involve types!". Might be worth searching for it and having a read. In fact, because I'm feeling so helpful this morning: http://www.digitalmars.com/d/archives/digitalmars/D/challenge_implement_the_max_function_47026.html Hope this helps -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Mar 13 2007
next sibling parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
Daniel Keep wrote:
 
 In the archives somewhere, there is a long thread discussing an
 implementation of min (or max; can't remember).  From what I do
 remember, it basically boiled down to "good grief this is actually
 really hard once you involve types!".

Doesn't the new mixin construct solve the issue?
Mar 13 2007
parent janderson <askme me.com> writes:
Hasan Aljudy wrote:
 
 
 Daniel Keep wrote:
 In the archives somewhere, there is a long thread discussing an
 implementation of min (or max; can't remember).  From what I do
 remember, it basically boiled down to "good grief this is actually
 really hard once you involve types!".

Doesn't the new mixin construct solve the issue?

Not unless you want to wrap your min/max statement's in mixins. I think this is overkill for min/max unless it was used for some higher level pattern. -Joel
Mar 13 2007
prev sibling parent freeagle <dalibor.free gmail.com> writes:
Daniel Keep wrote:
 freeagle wrote:
 Walter Bright wrote:
 torhu wrote:
 You can use typeof to get the common type, like this:

 typeof(T + U) max(T, U)(T arg1, U arg2)
 {
         return arg1 > arg2 ? arg1 : arg2;
 }

typeof(true ? cast(T)0 : cast(U)0) max(T, U)(T x1, U x2) { return x1 > x2 ? x1 : x2; }

typeof(true ? cast(T)0 : cast(U)0) And, i think this wont work for classes that overload the >,< etc operator, as you can't do cast(class)0, can you?

In the archives somewhere, there is a long thread discussing an implementation of min (or max; can't remember). From what I do remember, it basically boiled down to "good grief this is actually really hard once you involve types!". Might be worth searching for it and having a read. In fact, because I'm feeling so helpful this morning: http://www.digitalmars.com/d/archives/digitalmars/D/challenge_implement_the_max_function_47026.html Hope this helps -- Daniel

aha, sorry, i wasnt really followig the development and talk about D for 2 or 3 months, so missed it
Mar 13 2007
prev sibling parent reply "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail erdani.org> writes:
Walter Bright wrote:
 torhu wrote:
 You can use typeof to get the common type, like this:

 typeof(T + U) max(T, U)(T arg1, U arg2)
 {
         return arg1 > arg2 ? arg1 : arg2;
 }

The + isn't always defined, so you can use: typeof(true ? cast(T)0 : cast(U)0) max(T, U)(T x1, U x2) { return x1 > x2 ? x1 : x2; }

Is there a plan to allow: typeof(true ? x1 : x2) max(T, U)(T x1, U x2) { return x1 > x2 ? x1 : x2; } Andrei
Mar 13 2007
next sibling parent Walter Bright <newshound digitalmars.com> writes:
Andrei Alexandrescu (See Website For Email) wrote:
 Walter Bright wrote:
 torhu wrote:
 You can use typeof to get the common type, like this:

 typeof(T + U) max(T, U)(T arg1, U arg2)
 {
         return arg1 > arg2 ? arg1 : arg2;
 }

The + isn't always defined, so you can use: typeof(true ? cast(T)0 : cast(U)0) max(T, U)(T x1, U x2) { return x1 > x2 ? x1 : x2; }

Is there a plan to allow: typeof(true ? x1 : x2) max(T, U)(T x1, U x2) { return x1 > x2 ? x1 : x2; }

That should probably be made to work, too, but currently it doesn't.
Mar 14 2007
prev sibling parent =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
Andrei Alexandrescu wrote:

 Is there a plan to allow:
 
 typeof(true ? x1 : x2) max(T, U)(T x1, U x2)
 {
     return x1 > x2 ? x1 : x2;
 }

Is it impossibly hard or ambiguous to allow the compiler to infer the return type here? Something like
 auto max(T, U)(T x1, U x2)
 {
     return x1 > x2 ? x1 : x2;
 }

Mar 14 2007
prev sibling parent janderson <askme me.com> writes:
freeagle wrote:
 Hey all,
 
 from what I know, there is (currently?) no way of implementing min/max 
 template functions that could dynamically change return type depending 
 on the result of comparison. I think that this problem can be "solved" 
 easily. When used in C++, there is no problem with the return type as 
 min/max are coded as macros. But there is always probability that the 
 result of the min/max will be cast into appropriate type, because 
 variables cant be both float and int at the same time, for example.
 That means, when you write in C++
 
 float f = 1.0f, result;
 int a = 2;
 result = MAX(f, a);
 
 the result is cast to float when assignment to the variable is being 
 done. This means you always know of what type you want the result to be.
 I say we could move the casting into the function itself, like this:
 
 T max(T, U)(T arg1, U arg2)
 {
     return cast(T) (arg1 > arg2 ? arg1 : arg2);
 }
 
 and make it a standard that the type of the first argument will always 
 be the returning type of the min/max function.
 
 Just a thought
 
 freeagle

In C++ you can use some copy constructor / assignment magic with a proxy object to get the task done. That technique won't handle different types in the same query though. -Joel
Mar 13 2007