challenge: implement the max function

Don Clugston dac at nospam.com.au
Mon Jan 22 01:17:26 PST 2007


Alain wrote:
> Don Clugston Wrote:
> 
>> Andrei Alexandrescu (See Website For Email) wrote:
>>> Here's a simple challenge: implement the max function. Requirements:
>>>
>>> a) generic
>>> b) efficient
>>> c) preserve lvalueness when possible such that one can write e.g.
>>>
>>> max(arr[0], arr[1]) *= 0.9;
>>>
>>> d) should accept two or more arguments
>>> e) should return the "smartest" type, e.g. max of an unsigned int and 
>>> unsigned long should return unsigned long
>>> f) short and easy to understand
>>>
>>> I don't think it's possible to implement the function to the spec in 
>>> current D, so designs are allowed to invent new features, as long as 
>>> they define them thoroughly.
>>>
>>> Looking forward to any takers!
>>>
>>>
>>> Andrei
>> ----
>> Here's an implementation I put into Tango a few days ago. Unlike some 
>> other ones which have been posted, it does *not* require the types to 
>> support operator '+'. This was only for two arguments, but I believe it 
>> satisfies the other requirements. Should be easy to generalise.
>>
>> ----
>>
>> private {
>>      // Implicitly convert to the smallest type which can store both T 
>> and U; acts like an 'auto' template return type.
>> template SharedComparisonType(T, U) {
>>      static if (is( typeof( (T x, U y){ return y<x? y: x;}) Q == return))
>>          alias Q SharedComparisonType;
>> }
>> }
>>
>>
>> /** Return the minimum of x and y.
>>   *
>>   * Note: If x and y are floating-point numbers, and either is a NaN,
>>   * x will be returned.
>>   */
>> SharedComparisonType!(T, U) min(T, U)(T x, U y) {
>>      return y<x? y : x;
>> }
>>
>> /** Return the maximum of x and y.
>>   *
>>   * Note: If x and y are floating-point numbers, and either is a NaN,
>>   * x will be returned.
>>   */
>> SharedComparisonType!(T,U) max(T, U)(T x, U y) {
>>      return y>x? y : x;
>> }
> 
> Fine !
> but it doesn't work for the following common use case:
> int[] mylist=[1,2,3,4,5];
> int mymax=max(mylist);
> 
> Alain

Yes, as I said, it only works for the two-argument case.
It was intended as a direct replacement for C's
#define max(a, b) ((a)>(b)?(a):(b))

Just (for example) use Xinok's code, and replace typeof(X+Y) with 
SharedComparisonType!(X, Y).

Still doesn't solve (c) though; that's a really interesting challenge.

But since ?: doesn't preserve lvalues (ie, the following doesn't compile):

     real a = 5.2;
     real b = 3.1;
     (a> b? a : b) *= 0.7;

it seems to me that it's not really a template issue, but rather 
something even more fundamental.
(Interestingly,  auto c = (a> b? a : b).max; does compile; but if b is 
an int, and a is a real, it always returns real.max, even if b<a).




More information about the Digitalmars-d mailing list