Partial specialisation is foobarred?!

div0 div0 at users.sourceforge.net
Sun Aug 16 03:01:39 PDT 2009


-----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-----



More information about the Digitalmars-d mailing list