Thread overview
[Issue 2599] New: Two variadic parameters should be accepted
Jan 21, 2009
d-bugmail
Jan 24, 2009
d-bugmail
Jan 24, 2009
d-bugmail
Jan 25, 2009
d-bugmail
Jan 25, 2009
d-bugmail
Jan 25, 2009
d-bugmail
Jan 25, 2009
d-bugmail
January 21, 2009
http://d.puremagic.com/issues/show_bug.cgi?id=2599

           Summary: Two variadic parameters should be accepted
           Product: D
           Version: unspecified
          Platform: PC
        OS/Version: Linux
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla@digitalmars.com
        ReportedBy: andrei@metalanguage.com


The following code is not accepted:

void f(T1..., T2...)(T2 args)
{
    ...
}

However, it is unambiguous that T1 are supposed to be passed explicitly, whereas T2 bind to the arguments. Currently there is a workaround:

template f(T1...)
{
    alias fImpl!(T1).f f;
}

template fImpl(T1...)
{
    void f(T2...)(T2 args) { ... }
}

The workaround complicates code needlessly and introduces extraneous symbols.


-- 

January 24, 2009
http://d.puremagic.com/issues/show_bug.cgi?id=2599


smjg@iname.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |smjg@iname.com




------- Comment #1 from smjg@iname.com  2009-01-24 07:08 -------
How would you use such a thing?

The trouble is that F!(int, char[], Object) in itself is ambiguous - does T1
bind to int and T2 to (char[], Object), or T1 to (int, char[]) and T2 to
Object?  Even one to the empty tuple and the the other to the whole thing?
F!(int, char[], Object) would effectively have to be an internal, intermediate
template with the point of division as a parameter.

If you try to call the whole thing using IFTI, it's still ambiguous - what will T1 bind to?

Maybe it could be made to work, if the compiler can be made to try to match templates before expanding symbolic tuples under suitable conditions.


-- 

January 24, 2009
http://d.puremagic.com/issues/show_bug.cgi?id=2599





------- Comment #2 from andrei@metalanguage.com  2009-01-24 08:45 -------
(In reply to comment #1)
> How would you use such a thing?
> 
> The trouble is that F!(int, char[], Object) in itself is ambiguous - does T1
> bind to int and T2 to (char[], Object), or T1 to (int, char[]) and T2 to
> Object?  Even one to the empty tuple and the the other to the whole thing?
> F!(int, char[], Object) would effectively have to be an internal, intermediate
> template with the point of division as a parameter.
> 
> If you try to call the whole thing using IFTI, it's still ambiguous - what will T1 bind to?
> 
> Maybe it could be made to work, if the compiler can be made to try to match templates before expanding symbolic tuples under suitable conditions.
> 

When instantiated explicitly, all explicit arguments are eaten by T1. This is the purpose of the pattern: pass some explicit arguments, then deduce some more implicitly. Currently this is possible, but only with one ellipsis.


-- 

January 25, 2009
http://d.puremagic.com/issues/show_bug.cgi?id=2599





------- Comment #3 from smjg@iname.com  2009-01-25 08:54 -------
> When instantiated explicitly, all explicit arguments are eaten by T1.  This is the purpose of the pattern: pass some explicit arguments, then deduce some more implicitly.

In the current template system, a template is instantiated either implicitly or explicitly - no in-between.  At least, AIUI, the only exception is when one template argument is deduced from another, as in

    template temp(T : U[], U) {
        const string temp = "array of " ~ U.stringof;
    }

    pragma(msg, temp!(int[]));

To allow part-explicit, part-implicit template instantiations like you're asking for would be in itself a change in the language that must come first.

> Currently this is possible, but only with one ellipsis.

I'm not sure what you mean by this....

BTW your workaround can be written more simply:

    template f(T1...) {
        void f(T2...)(T2 args) { ... }
    }


-- 

January 25, 2009
http://d.puremagic.com/issues/show_bug.cgi?id=2599





------- Comment #4 from andrei@metalanguage.com  2009-01-25 09:09 -------
(In reply to comment #3)
> > When instantiated explicitly, all explicit arguments are eaten by T1.  This is the purpose of the pattern: pass some explicit arguments, then deduce some more implicitly.
> 
> In the current template system, a template is instantiated either implicitly or explicitly - no in-between.

Try this at home:

void fun(T1, T2)(T2 x)
{
}

void main()
{
    fun!(int)("a");
}


> To allow part-explicit, part-implicit template instantiations like you're asking for would be in itself a change in the language that must come first.

Already has (incidentally at my request.) It's used in much of std.algorithm.

> > Currently this is possible, but only with one ellipsis.
> 
> I'm not sure what you mean by this....

This works:

void fun(T1, T2, T3...)(T2 x, T3 xs)
{
}

void main()
{
    fun!(int)("a");
}

This doesn't, which is another bug:

void fun(T1, T2...)(T2 xs)
{
}

void main()
{
    fun!(int)("a");
}


> BTW your workaround can be written more simply:
> 
>     template f(T1...) {
>         void f(T2...)(T2 args) { ... }
>     }

Thanks!


-- 

January 25, 2009
http://d.puremagic.com/issues/show_bug.cgi?id=2599





------- Comment #5 from smjg@iname.com  2009-01-25 09:37 -------
(In reply to comment #4)
> Try this at home:
> 
> void fun(T1, T2)(T2 x)
> {
> }
> 
> void main()
> {
>     fun!(int)("a");
> }

But where's it documented?  Are you sure it isn't a bug that DMD accepts it?


-- 

January 25, 2009
http://d.puremagic.com/issues/show_bug.cgi?id=2599





------- Comment #6 from andrei@metalanguage.com  2009-01-25 09:46 -------
(In reply to comment #5)
> (In reply to comment #4)
> > Try this at home:
> > 
> > void fun(T1, T2)(T2 x)
> > {
> > }
> > 
> > void main()
> > {
> >     fun!(int)("a");
> > }
> 
> But where's it documented?  Are you sure it isn't a bug that DMD accepts it?

Not sure if Walter documented it. But I'm sure it's deliberately in there because I asked for the feature and Walter took the time to implement it. As far as I remember the feature was introduced in 2.015.


--