Partial specialisation is foobarred?!
Jason House
jason.james.house at gmail.com
Sun Aug 16 07:51:25 PDT 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-----
More information about the Digitalmars-d
mailing list