challenge #2: implement the varargs_reduce metafunction

Andrei Alexandrescu (See Website For Email) SeeWebsiteForEmail at erdani.org
Tue Jan 23 10:48:14 PST 2007


Christian Kamm wrote:
>> This one seems much more easy that the fist challenge, so I suspect 
>> I'm missing something.
> 
> Your implementation doesn't work with template functions. Here's a 
> rather straightforward implementation that seems to work:
> 
> template varargs_reduce(alias reduce2)
> {
> private:
>   template ReduceType(ARGS...)
>   {
>     static assert(ARGS.length >= 2, "requires >= 2 arguments");
> 
>     static if(ARGS.length == 2)
>       alias typeof(reduce2(ARGS[0], ARGS[1])) ReduceType;
>     else static if(ARGS.length > 2)
>       alias typeof(reduce2(ARGS[0], ReduceType!(ARGS[1..$]))) ReduceType;
>   }
> public:
>   // I'd have prefered a typeof(result) or typeof(return) as return type 
> here.
>   ReduceType!(ARGS) varargs_reduce(ARGS...)(ARGS args)
>   {
>     static assert(args.length >= 2, "requires >= 2 arguments");
>                
>     static if(args.length == 2)
>       auto result = reduce2(args[0], args[1]);
>     else static if(args.length > 2)
>       auto result = reduce2(args[0], varargs_reduce(args[1..$]));
>     
>     return result;
>   }
> }
> 
> typeof(T+Q) plus(T,Q)(T a, Q b)
> {
>   return a + b;
> }
> 
> void main()
> {
>   alias varargs_reduce!(plus).varargs_reduce plus_va;
>   plus_va(1, 2.1, 3i, 4u);
> }
> 
> While it compiles and seems to behave correctly, I'm suspicious of my 
> use of typeof in ReduceType - does the spec guarantee it does what I 
> want? I tried using is and std.traits.ReturnType but typeof lead to the 
> simplest solution.

This is a good solution. Ideally, you would combine it with Bruno 
Medeiros' idea to expand the template in a binary manner so as to spread 
dependencies.

One subtle point is that you don't want to use auto result = ...; We 
have not yet defined the semantics of transporting storage class 
entirely. It is possible that for backward compatibility reasons, auto 
will eliminate the 'inout' storage class that max2 so laboriously 
transported out. If that happens, your code will not compile. So the 
best bet is to simply return the reduce2 expression directly.

(Now I guess it's self-evident why I said earlier that D's handling of 
storage classes is a source of radioactive waste in the type system. It 
insidiously hits everywhere and when least expected.)

Great work, thanks!


Andrei



More information about the Digitalmars-d mailing list