www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Can someone explain this error?

reply Sean Kelly <sean invisibleduck.org> writes:
    class C
    {
        this() {}
        this( int x, int y ) {}
    }

    void main()
    {
        auto c = alloc!(C);
        auto d = alloc!(C)( 1, 2 );
    }

    T alloc(T, Params ...)( Params params )
    {
        return new T( params );
    }

$ dmd test
test.d(10): Error: expected 0 arguments, not 2
Sep 23 2008
next sibling parent reply "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Tue, Sep 23, 2008 at 7:26 PM, Sean Kelly <sean invisibleduck.org> wrote:
    class C
    {
        this() {}
        this( int x, int y ) {}
    }

    void main()
    {
        auto c = alloc!(C);
        auto d = alloc!(C)( 1, 2 );
    }

    T alloc(T, Params ...)( Params params )
    {
        return new T( params );
    }

 $ dmd test
 test.d(10): Error: expected 0 arguments, not 2

You cannot partially specify a template. alloc!(C) means that Params... is the empty tuple: hence, 0 arguments expected. template alloc(T) { T alloc(Params ...)( Params params ) { return new T( params ); } } does the trick, but requires you to call it with empty parens in the 0-param case (like "alloc!(C)()").
Sep 23 2008
parent reply Sean Kelly <sean invisibleduck.org> writes:
== Quote from Jarrett Billingsley (jarrett.billingsley gmail.com)'s article
 On Tue, Sep 23, 2008 at 7:26 PM, Sean Kelly <sean invisibleduck.org> wrote:
    class C
    {
        this() {}
        this( int x, int y ) {}
    }

    void main()
    {
        auto c = alloc!(C);
        auto d = alloc!(C)( 1, 2 );
    }

    T alloc(T, Params ...)( Params params )
    {
        return new T( params );
    }

 $ dmd test
 test.d(10): Error: expected 0 arguments, not 2

Params... is the empty tuple: hence, 0 arguments expected. template alloc(T) { T alloc(Params ...)( Params params ) { return new T( params ); } } does the trick, but requires you to call it with empty parens in the 0-param case (like "alloc!(C)()").

I'm pretty sure it's possible to partially specify a template. Consider: void main() { fn!(int)( 5 ); } void fn(A, B)( B b ) {} This works just fine, but if I change the function declaration to: void fn(A, B ...)( B b ) {} it fails. Are variadic templates a special case? Sean
Sep 23 2008
parent reply Sean Kelly <sean invisibleduck.org> writes:
== Quote from Jarrett Billingsley (jarrett.billingsley gmail.com)'s article
 On Tue, Sep 23, 2008 at 7:56 PM, Sean Kelly <sean invisibleduck.org> wrote:
 == Quote from Jarrett Billingsley (jarrett.billingsley gmail.com)'s article
 On Tue, Sep 23, 2008 at 7:26 PM, Sean Kelly <sean invisibleduck.org> wrote:
    class C
    {
        this() {}
        this( int x, int y ) {}
    }

    void main()
    {
        auto c = alloc!(C);
        auto d = alloc!(C)( 1, 2 );
    }

    T alloc(T, Params ...)( Params params )
    {
        return new T( params );
    }

 $ dmd test
 test.d(10): Error: expected 0 arguments, not 2

Params... is the empty tuple: hence, 0 arguments expected. template alloc(T) { T alloc(Params ...)( Params params ) { return new T( params ); } } does the trick, but requires you to call it with empty parens in the 0-param case (like "alloc!(C)()").

I'm pretty sure it's possible to partially specify a template. Consider: void main() { fn!(int)( 5 ); } void fn(A, B)( B b ) {} This works just fine, but if I change the function declaration to: void fn(A, B ...)( B b ) {} it fails. Are variadic templates a special case?


2.019 Sean
Sep 23 2008
parent Sean Kelly <sean invisibleduck.org> writes:
Bill Baxter wrote:
 I'm pretty sure it's possible to partially specify a template.  Consider:

    void main()
    {
        fn!(int)( 5 );
    }

    void fn(A, B)( B b ) {}

 This works just fine, but if I change the function declaration to:

    void fn(A, B ...)( B b ) {}

 it fails.  Are variadic templates a special case?



It seems all Andrei's usages of the feature in std.algorithm have an alias parameter as the first, followed by the variadic. So maybe this is just a code path in the compiler that hasn't been tickled previously. Does your code work if you make the first param an alias?

No. Weird, huh? void main() { int x; fn!(x)( 5 ); } void fn(alias a, B ...)( B b ) {} Sean
Sep 24 2008
prev sibling next sibling parent reply "Bill Baxter" <wbaxter gmail.com> writes:
On Wed, Sep 24, 2008 at 8:40 AM, Jarrett Billingsley
<jarrett.billingsley gmail.com> wrote:
 On Tue, Sep 23, 2008 at 7:26 PM, Sean Kelly <sean invisibleduck.org> wrote:
    class C
    {
        this() {}
        this( int x, int y ) {}
    }

    void main()
    {
        auto c = alloc!(C);
        auto d = alloc!(C)( 1, 2 );
    }

    T alloc(T, Params ...)( Params params )
    {
        return new T( params );
    }

 $ dmd test
 test.d(10): Error: expected 0 arguments, not 2

You cannot partially specify a template. alloc!(C) means that Params... is the empty tuple: hence, 0 arguments expected. template alloc(T) { T alloc(Params ...)( Params params ) { return new T( params ); } } does the trick, but requires you to call it with empty parens in the 0-param case (like "alloc!(C)()").

Ah, that works now? Good to know. At some point that wasn't working unless you did the full alloc!(C).alloc(params). --bb
Sep 23 2008
parent BCS <ao pathlink.com> writes:
Reply to Bill,


 Ah, that works now?  Good to know.  At some point that wasn't working
 unless you did the full alloc!(C).alloc(params).
 
 --bb
 

IIRC the full form doesn't work any more. If the shortcut form is allowed then the first alloc takes all the way to the inner function.
Sep 23 2008
prev sibling next sibling parent reply "Bill Baxter" <wbaxter gmail.com> writes:
On Wed, Sep 24, 2008 at 8:26 AM, Sean Kelly <sean invisibleduck.org> wrote:
    class C
    {
        this() {}
        this( int x, int y ) {}
    }

    void main()
    {
        auto c = alloc!(C);
        auto d = alloc!(C)( 1, 2 );
    }

    T alloc(T, Params ...)( Params params )
    {
        return new T( params );
    }

 $ dmd test
 test.d(10): Error: expected 0 arguments, not 2

This is the thing Walter made work in D2 but not D1. http://d.puremagic.com/issues/show_bug.cgi?id=493 You can sorta work around it by using nested templates. Then you can get a calling syntax like alloc!(C).D1_4ever; alloc!(C).D1_4ever(1,2); --bb
Sep 23 2008
parent Sean Kelly <sean invisibleduck.org> writes:
== Quote from Bill Baxter (wbaxter gmail.com)'s article
 On Wed, Sep 24, 2008 at 8:26 AM, Sean Kelly <sean invisibleduck.org> wrote:
    class C
    {
        this() {}
        this( int x, int y ) {}
    }

    void main()
    {
        auto c = alloc!(C);
        auto d = alloc!(C)( 1, 2 );
    }

    T alloc(T, Params ...)( Params params )
    {
        return new T( params );
    }

 $ dmd test
 test.d(10): Error: expected 0 arguments, not 2

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

Hm. It was D2 that gave me the error. Sean
Sep 23 2008
prev sibling next sibling parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Tue, Sep 23, 2008 at 7:56 PM, Sean Kelly <sean invisibleduck.org> wrote:
 == Quote from Jarrett Billingsley (jarrett.billingsley gmail.com)'s article
 On Tue, Sep 23, 2008 at 7:26 PM, Sean Kelly <sean invisibleduck.org> wrote:
    class C
    {
        this() {}
        this( int x, int y ) {}
    }

    void main()
    {
        auto c = alloc!(C);
        auto d = alloc!(C)( 1, 2 );
    }

    T alloc(T, Params ...)( Params params )
    {
        return new T( params );
    }

 $ dmd test
 test.d(10): Error: expected 0 arguments, not 2

Params... is the empty tuple: hence, 0 arguments expected. template alloc(T) { T alloc(Params ...)( Params params ) { return new T( params ); } } does the trick, but requires you to call it with empty parens in the 0-param case (like "alloc!(C)()").

I'm pretty sure it's possible to partially specify a template. Consider: void main() { fn!(int)( 5 ); } void fn(A, B)( B b ) {} This works just fine, but if I change the function declaration to: void fn(A, B ...)( B b ) {} it fails. Are variadic templates a special case? Sean

Uh, what compiler are you using? That fails for me (1.034).
Sep 23 2008
prev sibling next sibling parent "Bill Baxter" <wbaxter gmail.com> writes:
On Wed, Sep 24, 2008 at 9:08 AM, Sean Kelly <sean invisibleduck.org> wrote:
 == Quote from Bill Baxter (wbaxter gmail.com)'s article
 On Wed, Sep 24, 2008 at 8:26 AM, Sean Kelly <sean invisibleduck.org> wrote:
    class C
    {
        this() {}
        this( int x, int y ) {}
    }

    void main()
    {
        auto c = alloc!(C);
        auto d = alloc!(C)( 1, 2 );
    }

    T alloc(T, Params ...)( Params params )
    {
        return new T( params );
    }

 $ dmd test
 test.d(10): Error: expected 0 arguments, not 2

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

Hm. It was D2 that gave me the error.

Odd. This template is in std.algorithm for instance: Ranges[0] filter(alias pred, Ranges...)(Ranges rs) { ... } and called using filter!("a<10")(a); in the unittests. Here's the full code: ---------------------------------------------------------------------- Ranges[0] filter(alias pred, Ranges...)(Ranges rs) { alias unaryFun!(pred) fun; typeof(return) result; // Accumulate foreach (i, range; rs[0 .. $]) // all inputs { foreach (it; begin(range) .. end(range)) // current input { if (fun(*it)) result ~= *it; } } return result; } unittest { int[] a = [ 3, 4 ]; auto r = filter!("a > 3")(a); assert(r == [ 4 ]); a = [ 1, 22, 3, 42, 5 ]; auto under10 = filter!("a < 10")(a); assert(under10 == [1, 3, 5]); } ----------------------------------------------------
Sep 23 2008
prev sibling next sibling parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Tue, Sep 23, 2008 at 8:23 PM, Sean Kelly <sean invisibleduck.org> wrote:
 == Quote from Jarrett Billingsley (jarrett.billingsley gmail.com)'s article
 Uh, what compiler are you using?  That fails for me (1.034).

2.019

I suppose that would have been nice to know in the first place :|
Sep 23 2008
prev sibling next sibling parent "Bill Baxter" <wbaxter gmail.com> writes:
 I'm pretty sure it's possible to partially specify a template.  Consider:

    void main()
    {
        fn!(int)( 5 );
    }

    void fn(A, B)( B b ) {}

 This works just fine, but if I change the function declaration to:

    void fn(A, B ...)( B b ) {}

 it fails.  Are variadic templates a special case?


2.019

It seems all Andrei's usages of the feature in std.algorithm have an alias parameter as the first, followed by the variadic. So maybe this is just a code path in the compiler that hasn't been tickled previously. Does your code work if you make the first param an alias? --bb
Sep 23 2008
prev sibling parent Sergey Gromov <snake.scaly gmail.com> writes:
In article <gbbtue$1uam$1 digitalmars.com>, sean invisibleduck.org 
says...
     class C
     {
         this() {}
         this( int x, int y ) {}
     }
 
     void main()
     {
         auto c = alloc!(C);
         auto d = alloc!(C)( 1, 2 );
     }
 
     T alloc(T, Params ...)( Params params )
     {
         return new T( params );
     }
 
 $ dmd test
 test.d(10): Error: expected 0 arguments, not 2

I dug this case a bit more in 2.019. First of all, it's possible to make it work for non-zero argument count by making a single change in the template body: T alloc(T, Params ...)( Params params ) { cast(void) params; return new T( params ); } though it stops accepting zero arguments because "tuple has no effect in expression (tuple())". The weirdest part is when you try to access number of arguments in the tuple: void main() { auto d = alloc!(C)( 1, 2 ); } T alloc(T, Params ...)( Params params ) { cast(void) params; pragma( msg, Params.length.stringof ); return new T( params ); } when compiling, prints: 0u 2u but without the cast: 0u test.d(12): Error: expected 0 arguments, not 2 So it instantiates the template once, check whether the tuple argument is explicitly used inside the template body, then instantiates it again with number of arguments depending on the previous instantiation. Looks to me like a dirty hack in the compiler.
Sep 25 2008