Thread overview
About default parameters in variadic templates
Sep 17, 2012
Andrej Mitrovic
Sep 18, 2012
Don Clugston
Sep 18, 2012
Andrej Mitrovic
September 17, 2012
Related: http://d.puremagic.com/issues/show_bug.cgi?id=8676

This is something to think about for D3 (or maybe even D2 if it doesn't break code): it should be possible to inject default parameters in the function header rather than the body when using variadic templates. It would make auto-documentation possible and would make it easier to write template constraints. E.g. the current function header for lockstep() in std.range is:

auto lockstep(Args...)(Args args)
if (allSatisfy!(isInputRange, staticMap!(Unqual, Args)) || (
    allSatisfy!(isInputRange, staticMap!(Unqual, Args[0..$ - 1])) &&
    is(Args[$ - 1] == StoppingPolicy))

and the body:

static if (is(Args[$ - 1] == StoppingPolicy))
{
    alias args[0..$ - 1] ranges;
    alias Args[0..$ - 1] Ranges;
    alias args[$ - 1] stoppingPolicy;
}
else
{
    alias Args Ranges;
    alias args ranges;
    auto stoppingPolicy = StoppingPolicy.shortest;
}

A lot of code could be stripped if there was a way to set an optional last parameter for variadics. lockstep could then be written as:

auto newLockstep(Args...)(Args args, StoppingPolicy stoppingPolicy =
StoppingPolicy.shortest)
    if (allSatisfy!(isInputRange, staticMap!(Unqual, Args)))
{
    static if (Args.length > 1)
    {
        return Lockstep!(Args)(args, stoppingPolicy);
    }
    else
    {
        return args[0];
    }
}

So why doesn't this currently work? Using this template does compile:

    int[] arr1 = [1, 2, 3];
    int[] arr2 = [1, 2, 3, 4];

    foreach (x, y; newLockstep(arr1, arr2, StoppingPolicy.shortest))
    {
        writeln(x, " ", y);
    }

but if you don't specify the last StoppingPolicy argument at the call site it won't compile:

foreach (x, y; newLockstep(arr1, arr2)) { }

test.d(32): Error: template test.newLockstep does not match any
function template declaration
test.d(14): Error: template test.newLockstep(Args...) if
(allSatisfy!(isInputRange,staticMap!(Unqual,Args))) cannot deduce
template function from argument types !()(int[],int[])
September 18, 2012
On 17/09/12 14:42, Andrej Mitrovic wrote:
> Related: http://d.puremagic.com/issues/show_bug.cgi?id=8676

> A lot of code could be stripped if there was a way to set an optional
> last parameter for variadics. lockstep could then be written as:
>
> auto newLockstep(Args...)(Args args, StoppingPolicy stoppingPolicy =
> StoppingPolicy.shortest)
>      if (allSatisfy!(isInputRange, staticMap!(Unqual, Args)))
> {
>      static if (Args.length > 1)
>      {
>          return Lockstep!(Args)(args, stoppingPolicy);
>      }
>      else
>      {
>          return args[0];
>      }
> }

> but if you don't specify the last StoppingPolicy argument at the call
> site it won't compile:
>
> foreach (x, y; newLockstep(arr1, arr2)) { }
>
> test.d(32): Error: template test.newLockstep does not match any
> function template declaration
> test.d(14): Error: template test.newLockstep(Args...) if
> (allSatisfy!(isInputRange,staticMap!(Unqual,Args))) cannot deduce
> template function from argument types !()(int[],int[])

That just looks like a bug to me. Please enter it in Bugzilla.


September 18, 2012
On 9/18/12, Don Clugston <dac@nospam.com> wrote:
> That just looks like a bug to me. Please enter it in Bugzilla.

Ok: http://d.puremagic.com/issues/show_bug.cgi?id=8687

Hope Walter agrees with it.