challenge: implement the max function

Frits van Bommel fvbommel at REMwOVExCAPSs.nl
Sun Jan 21 12:35:03 PST 2007


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.


Some first thoughts:

Presumably, (b) is only required when using full optimization options?


I was going to ask "What is the 'smartest type' for the max of long and 
ulong?" but then I thought of the answer: ulong. Since the ulong is 
non-negative, the max of a long an an ulong will always be non-negative 
itself.


(c) & (e) are exclude each other in current D since return values are 
always rvalues, and a forwarding struct goes against requirement (e).

C++-like references won't work even if added, since the return type 
needs to be determined at compile time. This means you can't return an 
ulong& for max(uint, ulong) since if the uint happens to be larger you 
can't create the ulong& return value from the uint parameter.

Adding implicit casts and bending requirement (e) a little to return a 
forwarding struct that implicitly converts to the wanted type is another 
option.
This will probably breaks requirement (f) because of too much required 
operator overloading.
Also, you'll need to perform runtime checks for each operation if there 
were multiple types and you want to preserve lvalue-ness. This will 
likely break requirement (b).
That last objection could perhaps be mitigated by using a forwarding 
class instead of a struct though; runtime checks could then be replaced 
by virtual function calls. If that's efficient enough (b) is preserved.


Overall, I don't think this is possible in any statically typed 
programming language I know. I don't think even a C preprocessor macro 
can fulfill both (c) and (e) unless that "when possible" in (c) means 
"when possible in the language" instead of "when passed lvalues".



More information about the Digitalmars-d mailing list