Thread overview
BUG: Mixin' same template twice
Nov 08, 2005
Garett Bass
Nov 08, 2005
Regan Heath
Nov 08, 2005
Ivan Senji
Re: Mixin' same template twice
Nov 08, 2005
Garett Bass
Nov 08, 2005
Garett Bass
November 08, 2005
It may often be advantageous to reuse an algorithm for a variety of types, however this cannot currently be done via templates and mixins:

-------------------------

private import std.stdio;

template f(T) {
    T f(T x, T y) { return x + y; }
}

template g(T) {
    T g(T x, T y) { return x - y; }
}

class Bar {
    mixin f!(int);   // Ok
    mixin g!(int);   // Ok
    //mixin f!(float); // Error: mixin f is not a template
    //mixin g!(float); // Error: mixin g is not a template
}

alias f!(int)   fi;
alias f!(float) ff;

int main(char[][] args) {
    writefln("%d", fi(1, 2)); // Ok
    writefln("%f", ff(1.5, 2.5)); // Ok
    return 0;
}

-------------------------

Regards,
Garett


November 08, 2005
On Mon, 7 Nov 2005 21:53:26 -0600, Garett Bass <garettbass@studiotekne.com> wrote:
> private import std.stdio;
> template f(T) {
>     T f(T x, T y) { return x + y; }
> }
> template g(T) {
>     T g(T x, T y) { return x - y; }
> }
> class Bar {
>     mixin f!(int);   // Ok
>     mixin g!(int);   // Ok
>     //mixin f!(float); // Error: mixin f is not a template
>     //mixin g!(float); // Error: mixin g is not a template
> }
> alias f!(int)   fi;
> alias f!(float) ff;
> int main(char[][] args) {
>     writefln("%d", fi(1, 2)); // Ok
>     writefln("%f", ff(1.5, 2.5)); // Ok
>     return 0;
> }

Changing the templates to:

template f(T) {
    T fa(T x, T y) { return x + y; }
}

template g(T) {
    T ga(T x, T y) { return x - y; }
}

or anything other than 'f' and 'g' fixes the problem.

I guessed this because giving the mixin a scope name changes the error, see:

mixin f!(float) a;  //abug.Bar.f!(float) a f is not a template

(abug.d was my source file name)

Not sure if any of that helps.

Regan
November 08, 2005
Garett Bass wrote:
> It may often be advantageous to reuse an algorithm for a variety of types, however this cannot currently be done via templates and mixins:
> 
> -------------------------
> 
> private import std.stdio;
> 
> template f(T) {
>     T f(T x, T y) { return x + y; }
> }
> 
> template g(T) {
>     T g(T x, T y) { return x - y; }
> }
> 
> class Bar {
>     mixin f!(int);   // Ok
>     mixin g!(int);   // Ok
>     //mixin f!(float); // Error: mixin f is not a template
>     //mixin g!(float); // Error: mixin g is not a template
> }
> 


Changing Bar to:

class Bar {
    mixin f!(int);   // Ok
    mixin g!(int);   // Ok
    mixin .f!(float); // Error: mixin f is not a template
    mixin .g!(float); // Error: mixin g is not a template
}

Will make it compile but will cause ambiguity errors when method is called.

Change it to this to make it work:

class Bar {
    mixin .f!(int) f1;
    mixin .f!(float) f2;
    alias f1.f f;
    alias f2.f f;
}
November 08, 2005
Ok, I've redesigned my test case to include the suggested workaround (class Ugly).  This seems reasonable, though it would be nice if mixin could do the extra work automatically.

------------

module test;
private import std.stdio;

template F(T) {
    T f(T x, T y) { return x + y; }
}

class Good {
    mixin F!(int);
}

class Bad {
    mixin F!(int);
    mixin F!(float);
}

class Ugly {
    private mixin F!(byte)  fb;
    private mixin F!(int)   fi;
    private mixin F!(float) ff;
    public alias fb.f f;
    public alias fi.f f;
    public alias ff.f f;
}

int main(char[][] args) {
    Good good = new Good;
    writefln("%d", good.f(1, 2)); // Ok

    Bad bad = new Bad;
    //writefln("%d", bad.f(1, 2));     // Error
    //writefln("%f", bad.f(1.5, 2.5)); // Error

    Ugly ugly = new Ugly;
    writefln("%d", ugly.f(1, 2));     // Ok
    writefln("%f", ugly.f(1.5, 2.5)); // Ok
    return 0;
}


------------

 Regards,
Garett


November 08, 2005
So, it turns out that the ugly is even uglier than I thought.  The mixins have to be public in order for public aliases to be visible to other modules, which means that the uglified mixin identifiers are polluting the class interface.

-------------------------

module ugly;

template F(T) {
    T f(T x, T y) { return x + y; }
}

class Ugly {
    public mixin F!(byte)  fb;
    public mixin F!(int)   fi;
    public mixin F!(float) ff;
    public alias fb.f f;
    public alias fi.f f;
    public alias ff.f f;
}

-------------------------

module main;

private import std.stdio;

int main(char[][] args) {
    Ugly ugly = new Ugly;
    writefln("%d", ugly.f(1, 2));     // Ok
    writefln("%f", ugly.f(1.5, 2.5)); // Ok

    writefln("%d", ugly.fi(1, 2));     // UGLY!
    writefln("%f", ugly.ff(1.5, 2.5)); // UGLY!
    return 0;
}



-------------------------

 Regards,
Garett