digitalmars.D.learn - Template member functions conflicting
- Robin Allen (10/10) Feb 18 2007 class Bang(T)
- Jarrett Billingsley (11/20) Feb 18 2007 The page http://www.digitalmars.com/d/template-comparison.html says that...
- Bruno Medeiros (17/29) Feb 19 2007 They conflict, but there is an effective workaround, just turn the
- Aarti_pl (8/40) Feb 19 2007 Just a thought.
- Kirk McDonald (9/53) Feb 19 2007 Except that regular member functions and member function templates are
- Aarti_pl (10/14) Feb 19 2007 I was expecting that there are different for some reasons :-)
- Jarrett Billingsley (3/16) Feb 19 2007 Huh! Pretty sweet. :)
- Robin Allen (14/46) Feb 19 2007 I tried this, but for me it just crashes the compiler. Probably because
- Chris Nicholson-Sauls (8/60) Feb 19 2007 That won't typically work as you cannot overload on return types. If us...
- Bill Baxter (18/81) Feb 19 2007 No the rule is that you can't overload _only_ on return type. If the
- Robin Allen (7/96) Feb 20 2007 My code's changed so much now I can't even reproduce the bug. It was
class Bang(T) { void fn(U)( Bang!(U) ot) {} void fn(int q) {} } Why do the two member functions conflict here? One takes a class instance and a type, the other takes an int. If this is intended, and it's not possible to overload a function with a template function, then maybe it should be?
Feb 18 2007
"Robin Allen" <r.a3 ntlworld.com> wrote in message news:er9bin$1ksb$1 digitalmars.com...class Bang(T) { void fn(U)( Bang!(U) ot) {} void fn(int q) {} } Why do the two member functions conflict here? One takes a class instance and a type, the other takes an int. If this is intended, and it's not possible to overload a function with a template function, then maybe it should be?The page http://www.digitalmars.com/d/template-comparison.html says that it's unfortunately not possible. What's worse, you can use specialized template functions as that page suggests, but then you surrender IFTI, so you will no longer be able to write "b.fn(4)" and have it automatically determine that you want the int version. You'll have to write "b.fn!(int)(4)". The reason this isn't possible (I've heard) is that function overloading and template specialization are two completely separate concepts, and getting them to work together is very hard indeed.
Feb 18 2007
Robin Allen wrote:class Bang(T) { void fn(U)( Bang!(U) ot) {} void fn(int q) {} } Why do the two member functions conflict here? One takes a class instance and a type, the other takes an int. If this is intended, and it's not possible to overload a function with a template function, then maybe it should be?They conflict, but there is an effective workaround, just turn the function into a nullary template (template with zero parameters): import stdext.stdio; class Bang(T) { void fn(U)(Bang!(U) ot) { writeln("U template:", typeid(U) ); } void fn() (int q) { writeln("nullary template");} } void main(char[][] args) { auto foo = new Bang!(char); foo.fn(new Bang!(char)); foo.fn(42); } -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Feb 19 2007
Bruno Medeiros napisał(a):Robin Allen wrote:Just a thought. Couldn't be normal functions just discarded in favor of templated versions (without need to write 2 pairs of parenthesis of course - I mean internally in compiler)? It would probably be much more consistent with templated versions... Best Regards Marcin Kuszczakclass Bang(T) { void fn(U)( Bang!(U) ot) {} void fn(int q) {} } Why do the two member functions conflict here? One takes a class instance and a type, the other takes an int. If this is intended, and it's not possible to overload a function with a template function, then maybe it should be?They conflict, but there is an effective workaround, just turn the function into a nullary template (template with zero parameters): import stdext.stdio; class Bang(T) { void fn(U)(Bang!(U) ot) { writeln("U template:", typeid(U) ); } void fn() (int q) { writeln("nullary template");} } void main(char[][] args) { auto foo = new Bang!(char); foo.fn(new Bang!(char)); foo.fn(42); }
Feb 19 2007
Aarti_pl wrote:Bruno Medeiros napisał(a):Except that regular member functions and member function templates are not equivalent: Member function templates are implicitly "final," and are not entered into the vtable. -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.orgRobin Allen wrote:Just a thought. Couldn't be normal functions just discarded in favor of templated versions (without need to write 2 pairs of parenthesis of course - I mean internally in compiler)? It would probably be much more consistent with templated versions... Best Regards Marcin Kuszczakclass Bang(T) { void fn(U)( Bang!(U) ot) {} void fn(int q) {} } Why do the two member functions conflict here? One takes a class instance and a type, the other takes an int. If this is intended, and it's not possible to overload a function with a template function, then maybe it should be?They conflict, but there is an effective workaround, just turn the function into a nullary template (template with zero parameters): import stdext.stdio; class Bang(T) { void fn(U)(Bang!(U) ot) { writeln("U template:", typeid(U) ); } void fn() (int q) { writeln("nullary template");} } void main(char[][] args) { auto foo = new Bang!(char); foo.fn(new Bang!(char)); foo.fn(42); }
Feb 19 2007
Kirk McDonald napisał(a):Except that regular member functions and member function templates are not equivalent: Member function templates are implicitly "final," and are not entered into the vtable.I was expecting that there are different for some reasons :-) I am just thinking about improving it a little bit as I had to deal with overloading of template methods with normal functions and it is annoying.... Still, isn't it possible to make template functions like normal functions, so that they will not be 'final' by default? It would be probably also bonus for template functions itself... BR Marcin Kuszczak
Feb 19 2007
"Bruno Medeiros" <brunodomedeiros+spam com.gmail> wrote in message news:erc3nr$2lis$1 digitalmars.com...They conflict, but there is an effective workaround, just turn the function into a nullary template (template with zero parameters): import stdext.stdio; class Bang(T) { void fn(U)(Bang!(U) ot) { writeln("U template:", typeid(U) ); } void fn() (int q) { writeln("nullary template");} } void main(char[][] args) { auto foo = new Bang!(char); foo.fn(new Bang!(char)); foo.fn(42); }Huh! Pretty sweet. :)
Feb 19 2007
Bruno Medeiros wrote:Robin Allen wrote:I tried this, but for me it just crashes the compiler. Probably because it's actually opMul I'm defining rather than a normal function. (I'm trying to make a Matrix class that you can multiply by another matrix or a vector.) The actual code is more like this: class Matrix(int X,int Y,T) { Matrix!(X,OY,T) opMul(OY)( Matrix!(Y,OY,T) ot ); Vector!(Y,T) opMul( Vector!(X,T) vec ); } The only way I've been able to do it is by replacing one of the operator functions with a regular function. But it would be nice to do it with the * sign.class Bang(T) { void fn(U)( Bang!(U) ot) {} void fn(int q) {} } Why do the two member functions conflict here? One takes a class instance and a type, the other takes an int. If this is intended, and it's not possible to overload a function with a template function, then maybe it should be?They conflict, but there is an effective workaround, just turn the function into a nullary template (template with zero parameters): import stdext.stdio; class Bang(T) { void fn(U)(Bang!(U) ot) { writeln("U template:", typeid(U) ); } void fn() (int q) { writeln("nullary template");} } void main(char[][] args) { auto foo = new Bang!(char); foo.fn(new Bang!(char)); foo.fn(42); }
Feb 19 2007
Robin Allen wrote:Bruno Medeiros wrote:That won't typically work as you cannot overload on return types. If user code /only ever/ passed either Matrix or Vector with your opMul it might pass... but I'm dubious. In this case I would recommend just defining opMul for Matrix, and providing a function for multiplying with a Vector. The fact that it crashes the compiler, though, is another manner. Try to find a small test case that produces it and you may have a bug report to file. -- Chris Nicholson-SaulsRobin Allen wrote:I tried this, but for me it just crashes the compiler. Probably because it's actually opMul I'm defining rather than a normal function. (I'm trying to make a Matrix class that you can multiply by another matrix or a vector.) The actual code is more like this: class Matrix(int X,int Y,T) { Matrix!(X,OY,T) opMul(OY)( Matrix!(Y,OY,T) ot ); Vector!(Y,T) opMul( Vector!(X,T) vec ); } The only way I've been able to do it is by replacing one of the operator functions with a regular function. But it would be nice to do it with the * sign.class Bang(T) { void fn(U)( Bang!(U) ot) {} void fn(int q) {} } Why do the two member functions conflict here? One takes a class instance and a type, the other takes an int. If this is intended, and it's not possible to overload a function with a template function, then maybe it should be?They conflict, but there is an effective workaround, just turn the function into a nullary template (template with zero parameters): import stdext.stdio; class Bang(T) { void fn(U)(Bang!(U) ot) { writeln("U template:", typeid(U) ); } void fn() (int q) { writeln("nullary template");} } void main(char[][] args) { auto foo = new Bang!(char); foo.fn(new Bang!(char)); foo.fn(42); }
Feb 19 2007
Chris Nicholson-Sauls wrote:Robin Allen wrote:No the rule is that you can't overload _only_ on return type. If the arguments are distinct then you can overload. This works for instance: struct Foo { int frob(int a) { return a; } char[] frob(char[] a) { return a; } } void main() { Foo f; int x = f.frob(3); char[] y = f.frob("hithere"); }Bruno Medeiros wrote:That won't typically work as you cannot overload on return types.Robin Allen wrote:I tried this, but for me it just crashes the compiler. Probably because it's actually opMul I'm defining rather than a normal function. (I'm trying to make a Matrix class that you can multiply by another matrix or a vector.) The actual code is more like this: class Matrix(int X,int Y,T) { Matrix!(X,OY,T) opMul(OY)( Matrix!(Y,OY,T) ot ); Vector!(Y,T) opMul( Vector!(X,T) vec ); } The only way I've been able to do it is by replacing one of the operator functions with a regular function. But it would be nice to do it with the * sign.class Bang(T) { void fn(U)( Bang!(U) ot) {} void fn(int q) {} } Why do the two member functions conflict here? One takes a class instance and a type, the other takes an int. If this is intended, and it's not possible to overload a function with a template function, then maybe it should be?They conflict, but there is an effective workaround, just turn the function into a nullary template (template with zero parameters): import stdext.stdio; class Bang(T) { void fn(U)(Bang!(U) ot) { writeln("U template:", typeid(U) ); } void fn() (int q) { writeln("nullary template");} } void main(char[][] args) { auto foo = new Bang!(char); foo.fn(new Bang!(char)); foo.fn(42); }If user code /only ever/ passed either Matrix or Vector with your opMul it might pass... but I'm dubious. In this case I would recommend just defining opMul for Matrix, and providing a function for multiplying with a Vector.The fact that it crashes the compiler, though, is another manner. Try to find a small test case that produces it and you may have a bug report to file.Yeh, that sounds like a bug. File it here when you have a small repro case: http://d.puremagic.com/issues/ --bb
Feb 19 2007
My code's changed so much now I can't even reproduce the bug. It was probably caused by something way off in another file, like when I forgot a return statement and all my unittests crashed. Also, I had (OY) by mistake, rather than (int OY). Template syntax is pretty confusing. I think I preferred C++'s (typename T) to D's (T). But that might be just me. Bill Baxter wrote:Chris Nicholson-Sauls wrote:Robin Allen wrote:No the rule is that you can't overload _only_ on return type. If the arguments are distinct then you can overload. This works for instance: struct Foo { int frob(int a) { return a; } char[] frob(char[] a) { return a; } } void main() { Foo f; int x = f.frob(3); char[] y = f.frob("hithere"); }Bruno Medeiros wrote:That won't typically work as you cannot overload on return types.Robin Allen wrote:I tried this, but for me it just crashes the compiler. Probably because it's actually opMul I'm defining rather than a normal function. (I'm trying to make a Matrix class that you can multiply by another matrix or a vector.) The actual code is more like this: class Matrix(int X,int Y,T) { Matrix!(X,OY,T) opMul(OY)( Matrix!(Y,OY,T) ot ); Vector!(Y,T) opMul( Vector!(X,T) vec ); } The only way I've been able to do it is by replacing one of the operator functions with a regular function. But it would be nice to do it with the * sign.class Bang(T) { void fn(U)( Bang!(U) ot) {} void fn(int q) {} } Why do the two member functions conflict here? One takes a class instance and a type, the other takes an int. If this is intended, and it's not possible to overload a function with a template function, then maybe it should be?They conflict, but there is an effective workaround, just turn the function into a nullary template (template with zero parameters): import stdext.stdio; class Bang(T) { void fn(U)(Bang!(U) ot) { writeln("U template:", typeid(U) ); } void fn() (int q) { writeln("nullary template");} } void main(char[][] args) { auto foo = new Bang!(char); foo.fn(new Bang!(char)); foo.fn(42); }If user code /only ever/ passed either Matrix or Vector with your opMul it might pass... but I'm dubious. In this case I would recommend just defining opMul for Matrix, and providing a function for multiplying with a Vector.The fact that it crashes the compiler, though, is another manner. Try to find a small test case that produces it and you may have a bug report to file.Yeh, that sounds like a bug. File it here when you have a small repro case: http://d.puremagic.com/issues/ --bb
Feb 20 2007