Template argument deduction from a function call question

Steven Schveighoffer via Digitalmars-d digitalmars-d at puremagic.com
Thu Apr 2 06:47:13 PDT 2015


On 4/1/15 2:46 PM, Dzugaru wrote:
> On Wednesday, 1 April 2015 at 18:37:24 UTC, Ali Çehreli wrote:
>> On 04/01/2015 11:27 AM, Dzugaru wrote:
>>
>> > This code does work when you provide second (non-default)
>> argument to
>> > function, and doesn't if you do not (no way it can deduce E
>> solely from
>> > checks I assume).
>> >
>> > My version, in constract, works when you do not provide
>> second argument
>> > and doesn't if you do.
>>
>> Another attempt:
>>
>> import std.range;
>>
>> ElementType!S
>> aggregate(alias func, S, E = ElementType!S)(S list, E accum = E.init)
>>     if(is(typeof(func(accum, accum)) == typeof(accum)))
>> {
>>     foreach(ref e; list) {
>>         accum = func(accum, e);
>>     }
>>
>>     return accum;
>> }
>>
>> void main()
>> {
>>     auto min1 = aggregate!((a,  b) { return a < b ? a : b;
>> })([2,4,1,3,5], int.max);
>>     auto min2 = aggregate!((a,  b) { return a < b ? a : b;
>> })([2,4,1,3,5]);
>>
>>     assert(min1 == 1);
>>     assert(min2 == 0);
>> }
>>
>> Ali
>
> This is perfect, many thanks. Didn't know I can use "=" in template
> parameter list.

I'd still put the template constraint in: if(is(E == ElementType!S)), 
because using = in the template parameter list does not constrain it to 
that type, it just gives a default.

However, you could also change the function signature to allow more 
flexibility:

auto
aggregate(alias func, S, E = ElementType!S)(S list, E accum = E.init)
     if(is(typeof(accum = func(accum, ElementType!S.init))))

But then again, you can use reduce ;)

-Steve


More information about the Digitalmars-d mailing list