Thread overview
Varargs and default arguments
Oct 06, 2015
Nick Sabalausky
Oct 06, 2015
anonymous
Oct 07, 2015
anonymous
October 06, 2015
Ok, D-style varargs can accept a parameter length of zero:

---------------
void foo(T...)(T args) {
    //...
}
foo();
foo(t1, t2);
---------------

Is there any way to stick a param with a default value before that?

---------------
void foo(T...)(string str=null, T args=/+what goes here???+/) {
    //...
}
foo();
foo(str);
foo(str, t1, t2);
---------------

Obviously this can be worked around easily enough by splitting it into two overloads ("foo(string str=null)" and "foo(string str, T args)"), but is there a way to do it in one?
October 06, 2015
On Tuesday 06 October 2015 22:01, Nick Sabalausky wrote:

> Ok, D-style varargs can accept a parameter length of zero:
> 
> ---------------
> void foo(T...)(T args) {
>      //...
> }
> foo();
> foo(t1, t2);
> ---------------

Terminology fun:

The spec uses the term "D-style variadic function" for something else yet: `int abc(char c, ...);` -- http://dlang.org/function.html#variadic

Yours is technically a "variadic function template", I guess, i.e., a function template that's variadic, not a template of a variadic function.

> Is there any way to stick a param with a default value before that?
> 
> ---------------
> void foo(T...)(string str=null, T args=/+what goes here???+/) {
>      //...
> }
> foo();
> foo(str);
> foo(str, t1, t2);
> ---------------
> 
> Obviously this can be worked around easily enough by splitting it into two overloads ("foo(string str=null)" and "foo(string str, T args)"), but is there a way to do it in one?

You can put an expression tuple ("expression AliasSeq"??) there. T.init is one that always fits T's types. But you could generate one with different values, too.

----
void foo(T...)(string str=null, T args = T.init) {
	//...
}
void main()
{
	foo();
	foo("");
	foo("", 1, 2);
}
----
October 07, 2015
On 10/6/15 4:27 PM, anonymous wrote:
>
> You can put an expression tuple ("expression AliasSeq"??) there. T.init is
> one that always fits T's types. But you could generate one with different
> values, too.
>
> ----
> void foo(T...)(string str=null, T args = T.init) {
> 	//...
> }
> void main()
> {
> 	foo();
> 	foo("");

What is T in this case? I wondered, and it is an empty expression tuple (prints out as "()"). Interesting.

Note, this doesn't seem to work on 2.067.

There are other ways to solve this too:

void foo() {return foo(null);}
void foo(T...)(string str, T args) {...}

I find it quite fascinating that in anonymous' solution, the T.init doesn't ever actually get used!

-Steve
October 07, 2015
On Wednesday 07 October 2015 02:22, Steven Schveighoffer wrote:

> On 10/6/15 4:27 PM, anonymous wrote:
[...]
>> void foo(T...)(string str=null, T args = T.init) {
[...]
> I find it quite fascinating that in anonymous' solution, the T.init doesn't ever actually get used!

It's not used with IFTI, but if you instantiate the template explicitly, the defaults arguments come up.

Or rather, they should come up. It doesn't seem to work:

----
void foo(T ...)(T args = T.init) {}
void main()
{
    foo!(int, float)(); /* Error: foo (int _param_0, float _param_1) is not
callable using argument types () */
}
----

I filed an issue: https://issues.dlang.org/show_bug.cgi?id=15170