www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Partial specialisation is foobarred?!

reply div0 <div0 users.sourceforge.net> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I've been poking around on the bug track and can't find a specific bug
report, but it seems unlikely this hasn't been noticed before.

This is w/ dmd 2.031 & 1.046

//========================
import std.stdio;

struct nil {
}

class D(T) {
    uint  _len;
    T	  _val;

    this(uint l, T v) {	_len = l; _val = v; }

    // method 0 - to be called with most D!(*)
    // where only _len is common
    void f(M)(M rhs) {
        _len = rhs._len;
        writefln("method 0");
    }

    // method 1 - specalization for D!(nil) types
    // - set _len to invalid
    void f(M : D!(nil))(D!(nil) rhs) {
        _len = cast(uint)(-1);
        writefln("method 1");
    }

    // method 2 - specalization for this type - copy all values
    // - how many ways we can write this and which is correct?
    //void f(M : D!(T))(D!(T) rhs) {
    //void f(M : D!(N), N : T)(D!(T) rhs) {
    //void f(M : D!(N), N : int)(D!(T) rhs) {
    void f(M : D!(int))(D!(T) rhs) {
        _len = rhs._len;
        _val = rhs._val;
        writefln("method 2");
    }

// we can't do this, it conflicts with template functions
version(none):
    void f(D!(T) rhs) {}
}

class D(T : nil) {
}

int main(char[][]argv) {
    auto    c0 = new D!(int)(1, 9);
    auto    c1 = new D!(int)(3, 18);
    auto    c2 = new D!(nil)();

    // *should* call method 2, but calls method 0
    writef("want method 2, getting: ");
    c0.f(c1);

version(none) {
    // *should* call method 1, but calls method 0 which is a
    // compile error; rather unhelpfully it's an error w/o
    // giving instantiation line
    writef("want method 1, getting: ");
    c0.f!()(c2);
}

    // force correct call to method 1
    writef("want method 1, getting: ");
    c0.f!(D!(nil))(c2);

    // try & force correct call to method 2, but fails
    // (will all 4 sigs), it picks method 0
    writef("want method 2, getting: ");
    c0.f!(D!(int))(c1);

    // interestingly...
    writef("want method 1, getting: ");
    c0.f!(typeof(c2))(c2);		// calls method 1

    // but doesn't work all the time
    writef("want method 2, getting: ");
    c0.f!(typeof(c0))(c1);		// calls method 0

    return 0;
}





FYI, the equivalent c++ works fine:


//========================
struct nil {
};

template< typename T >
class D {
public:
   unsigned _len;
   T        _val;

   D(unsigned l, T v) { _len = l; _val = v; }

   // method 0 - to be called with most D!(*) where only _len is common
   template< typename M >
   void f(const M &rhs) {
      _len = rhs._len;
      ATLTRACE("method 0\n");
   }

   // method 1 - specalization for D!(nil) types - set _len to invalid
   template<>
   void f< D<nil> >(const D<nil>& /*rhs*/) {
      _len = static_cast< unsigned >(-1);
      ATLTRACE("method 1\n");
   }

   // method 2 - specalization for this type - copy all values
   template<>
   void f< D< T > >(const D< T >& rhs) {
      _len = rhs._len;
      _val = rhs._val;
      ATLTRACE("method 2\n");
   }
};

template<>
class D< nil > {
public:
};

void test() {
   D<int>   c0(1, 9);
   D<int>   c1(2, 18);
   D<nil>   c2;
   D<void*> c3(3, 0);

   c0.f(c1); // call method 2
   c0.f(c2); // call method 1
   c0.f(c3); // call method 0
}

- --
My enormous talent is exceeded only by my outrageous laziness.
http://www.ssTk.co.uk
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iD8DBQFKh9kDT9LetA9XoXwRAivoAJ9sqIdzPJf1cialdpk8EE9VkBwG7gCbB+l5
xXxZw9FX80nJjXRa9X2PhDM=
=Tetp
-----END PGP SIGNATURE-----
Aug 16 2009
parent reply Jason House <jason.james.house gmail.com> writes:
FWIW, I usually use static if instead of specialization. In D2, you can also
use if expressions as part of the template declaration. As far as your code
below, I think the declaration of M without using it is suspect. I don't have a
compiler to play with right now...

div0 Wrote:

 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1
 
 I've been poking around on the bug track and can't find a specific bug
 report, but it seems unlikely this hasn't been noticed before.
 
 This is w/ dmd 2.031 & 1.046
 
 //========================
 import std.stdio;
 
 struct nil {
 }
 
 class D(T) {
     uint  _len;
     T	  _val;
 
     this(uint l, T v) {	_len = l; _val = v; }
 
     // method 0 - to be called with most D!(*)
     // where only _len is common
     void f(M)(M rhs) {
         _len = rhs._len;
         writefln("method 0");
     }
 
     // method 1 - specalization for D!(nil) types
     // - set _len to invalid
     void f(M : D!(nil))(D!(nil) rhs) {
         _len = cast(uint)(-1);
         writefln("method 1");
     }
 
     // method 2 - specalization for this type - copy all values
     // - how many ways we can write this and which is correct?
     //void f(M : D!(T))(D!(T) rhs) {
     //void f(M : D!(N), N : T)(D!(T) rhs) {
     //void f(M : D!(N), N : int)(D!(T) rhs) {
     void f(M : D!(int))(D!(T) rhs) {
         _len = rhs._len;
         _val = rhs._val;
         writefln("method 2");
     }
 
 // we can't do this, it conflicts with template functions
 version(none):
     void f(D!(T) rhs) {}
 }
 
 class D(T : nil) {
 }
 
 int main(char[][]argv) {
     auto    c0 = new D!(int)(1, 9);
     auto    c1 = new D!(int)(3, 18);
     auto    c2 = new D!(nil)();
 
     // *should* call method 2, but calls method 0
     writef("want method 2, getting: ");
     c0.f(c1);
 
 version(none) {
     // *should* call method 1, but calls method 0 which is a
     // compile error; rather unhelpfully it's an error w/o
     // giving instantiation line
     writef("want method 1, getting: ");
     c0.f!()(c2);
 }
 
     // force correct call to method 1
     writef("want method 1, getting: ");
     c0.f!(D!(nil))(c2);
 
     // try & force correct call to method 2, but fails
     // (will all 4 sigs), it picks method 0
     writef("want method 2, getting: ");
     c0.f!(D!(int))(c1);
 
     // interestingly...
     writef("want method 1, getting: ");
     c0.f!(typeof(c2))(c2);		// calls method 1
 
     // but doesn't work all the time
     writef("want method 2, getting: ");
     c0.f!(typeof(c0))(c1);		// calls method 0
 
     return 0;
 }
 
 
 
 
 
 FYI, the equivalent c++ works fine:
 
 
 //========================
 struct nil {
 };
 
 template< typename T >
 class D {
 public:
    unsigned _len;
    T        _val;
 
    D(unsigned l, T v) { _len = l; _val = v; }
 
    // method 0 - to be called with most D!(*) where only _len is common
    template< typename M >
    void f(const M &rhs) {
       _len = rhs._len;
       ATLTRACE("method 0\n");
    }
 
    // method 1 - specalization for D!(nil) types - set _len to invalid
    template<>
    void f< D<nil> >(const D<nil>& /*rhs*/) {
       _len = static_cast< unsigned >(-1);
       ATLTRACE("method 1\n");
    }
 
    // method 2 - specalization for this type - copy all values
    template<>
    void f< D< T > >(const D< T >& rhs) {
       _len = rhs._len;
       _val = rhs._val;
       ATLTRACE("method 2\n");
    }
 };
 
 template<>
 class D< nil > {
 public:
 };
 
 void test() {
    D<int>   c0(1, 9);
    D<int>   c1(2, 18);
    D<nil>   c2;
    D<void*> c3(3, 0);
 
    c0.f(c1); // call method 2
    c0.f(c2); // call method 1
    c0.f(c3); // call method 0
 }
 
 - --
 My enormous talent is exceeded only by my outrageous laziness.
 http://www.ssTk.co.uk
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.7 (MingW32)
 Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
 
 iD8DBQFKh9kDT9LetA9XoXwRAivoAJ9sqIdzPJf1cialdpk8EE9VkBwG7gCbB+l5
 xXxZw9FX80nJjXRa9X2PhDM=
 =Tetp
 -----END PGP SIGNATURE-----

Aug 16 2009
parent div0 <div0 users.sourceforge.net> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jason House wrote:
 FWIW, I usually use static if instead of specialization. In D2, you can also
use if expressions as part of the template declaration. As far as your code
below, I think the declaration of M without using it is suspect. I don't have a
compiler to play with right now...
 

ty. - -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iD8DBQFKiC0pT9LetA9XoXwRAm6gAJ9QNC/LioDVeTbSCf6+xYGdJnm1uwCgudnl Rk7P9mewn9WK7nlLfGQvCak= =wO2/ -----END PGP SIGNATURE-----
Aug 16 2009