digitalmars.D - Partial specialisation is foobarred?!
- div0 (123/123) Aug 16 2009 -----BEGIN PGP SIGNED MESSAGE-----
- Jason House (2/161) Aug 16 2009
- div0 (15/17) Aug 16 2009 -----BEGIN PGP SIGNED MESSAGE-----
-----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
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
-----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...Ah the M. Sweet that sorted it. 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