challenge: implement the max function

Andrei Alexandrescu (See Website For Email) SeeWebsiteForEmail at erdani.org
Fri Jan 26 16:04:14 PST 2007


Kevin Bealer wrote:
> Here's my late entry:
> 
> alias max_type(T, U) {
>   static if (T.max > U.max) {
>     alias T max_type;
>   } else {
>     alias U max_type;
>   }
> }

So far so good.

> max_type(T, U) ALIAS max(T, U)(inout T x, inout U y)
> {
>     alias max_type(T,U) MT;
>     MT x1 = x, y1 = y;
> 
>     if (x1 >= y1) {
>         static if (is (MT == T)) {
>             return alias x;
>         } else {
>             return x1;
>         }
>     } else {
>         static if (is (MT == U)) {
>             return alias y;
>         } else {
>             return y1;
>         }
>     }
> }

This will not work when passed lvalues, a la:

auto b = max(a + 1, a - 1);

> The new feature is "return alias x", which is just syntax for saying 
> that you are returning a reference to the input parameter.

The reference thing must be reflected in function's return type, not in 
the function's return statement(s). This is for a number of reasons, 
including separate compilation and ease of parsing.

> Note that "ALIAS" should be replaced by some keyword -- or maybe remvoed 
> entirely, since it can be deduced easily as described below.  It should 
> be safe to remove it entirely since we can deduce it from the I was 
> going to use "alias" but it looks too much like If D ever gets a keyword 
> to indicate the opposite of C++'s "strict" keyword, I would think it 
> could be used here.

I'm not sure what the purpose of ALIAS is. Was it to indicate that max 
returns, or may return, a reference?

In any case, the entry needs some rework because of the reason above: 
it's not sound to deduce storage from the function's return value, 
without actually reflecting that storage in the statically-known return 
type.

Moving on to the second entry...

> Solution Two
> 
> NOTE: This is not a C++ "&", see below.
> 
> template max(T, U) {
>   static if (T == U) {
>     T & max(T & x, U & y)
>     {
>       if (*x >= *y) {
>         return x;
>       } else {
>         return y;
>       }
>     }
>   } else {
>     max_type(T, U) max(T, U)(T x, U y)
>     {
>       alias max_type(T,U) MT;
> 
>       if (x >= y) {
>         return x;
>       } else {
>         return y;
>       }
>     }
>   }
> }
 >
> The "&" here is kind of like C++'s "&" type, but you can't use it except 
> in function interfaces.  In the context of a function argument, it means 
> that the caller of the function is actually passing "& x" when they say 
> "x", and in the case of a return value, the caller thinks they get 
> something like "T x", but it they actually get a "T * x", and when they 
> use it, the "x" turns into "*x".

What if I call max with two rvalues of the same type?

auto b = max(a + 1, a + 1);

> Inside the function body, no magic translations are done, the writer of 
> the function use actual pointers to do the work to make it harder to 
> accidentally return addresses of local variables.
> 
> I think this satisfies A B C E F, though not as heroicly with C as the 
> Solution One (which may be a good thing.)

But rvalue handling is not satisfactory, and besides there is the scary 
code duplication. I'm afraid this candidate needs some rework too :o).


Andrei



More information about the Digitalmars-d mailing list