www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - BUG: Mixin' same template twice

reply "Garett Bass" <garettbass studiotekne.com> writes:
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 
Nov 07 2005
next sibling parent "Regan Heath" <regan netwin.co.nz> writes:
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
Nov 07 2005
prev sibling next sibling parent Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
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; }
Nov 07 2005
prev sibling next sibling parent "Garett Bass" <garettbass studiotekne.com> writes:
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
Nov 08 2005
prev sibling parent "Garett Bass" <garettbass studiotekne.com> writes:
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
Nov 08 2005