digitalmars.D - Limited member function templates?
- Janice Caron (22/22) Nov 09 2007 I get why member function templates would be a bad idea in general.
- Bill Baxter (5/37) Nov 09 2007 Member function templates have worked fine as long as I've been around.
- Janice Caron (19/22) Nov 09 2007 Really? The documentation at http://digitalmars.com/d/template.html says...
- Bill Baxter (19/48) Nov 10 2007 Well, this works (dmd 1.023):
- Janice Caron (7/8) Nov 10 2007 Wow!
- Steven Schveighoffer (25/33) Nov 10 2007 In fact, the code identified in the document that is an "Error" actually...
- Christian Kamm (2/5) Nov 11 2007 I think that's bug 566 from last year:
- Janice Caron (7/12) Nov 09 2007 When we get the common calling convention whereby f(x) and x.f() are
- Christopher Wright (9/24) Nov 10 2007 I was just about to feature-request virtual templated member functions.
- Daniel Keep (32/59) Nov 10 2007 Think about what you're asking for. An interface defines, essentially,
- Yigal Chripun (15/42) Nov 10 2007 I may be mistaken, but isn't it enough to use the following:
- Nathan Reed (7/16) Nov 11 2007 Unfortunately that doesn't quite work. Even if a bicycle is-a vehicle,
- Michel Fortin (9/18) Nov 10 2007 Why don't you try `mixin` instead of `alias`? Then I think you can even
- Christopher Wright (11/55) Nov 10 2007 A Collection!(Bicycle) is not a Collection!(Vehicle). You cannot add arb...
I get why member function templates would be a bad idea in general. They'd be a nightmare to implement! But it occurs to me that if we insist on some limitations, it might be quite feasible, within those limitations. The limitation I have in mind is explicit instantiation. Here's an example of what I'm thinking of. class A { string s; int f(T)(T t) { s = toUTF8(t); } /* template member function */ alias f!(string) fs; /* explicit instantiation */ alias f!(wstring) fw; /* explicit instantiation */ } The trick is that the instantiation must be done *within the class definition*. We can still disallow anything not explicitly instantiated inside the class definition, so A a; a.fs("hello"); /* OK - uses alias*/ a.f!(string)("hello") /* OK - template is instantiated for string */ string s; a.f(s); /* OK - type deduction */ a.f!(dstring)("hello"d) /* Not OK - template not instantiated for dstring */ Thoughts?
Nov 09 2007
Janice Caron wrote:I get why member function templates would be a bad idea in general. They'd be a nightmare to implement! But it occurs to me that if we insist on some limitations, it might be quite feasible, within those limitations. The limitation I have in mind is explicit instantiation. Here's an example of what I'm thinking of. class A { string s; int f(T)(T t) { s = toUTF8(t); } /* template member function */ alias f!(string) fs; /* explicit instantiation */ alias f!(wstring) fw; /* explicit instantiation */ } The trick is that the instantiation must be done *within the class definition*. We can still disallow anything not explicitly instantiated inside the class definition, so A a; a.fs("hello"); /* OK - uses alias*/ a.f!(string)("hello") /* OK - template is instantiated for string */ string s; a.f(s); /* OK - type deduction */ a.f!(dstring)("hello"d) /* Not OK - template not instantiated for dstring */ Thoughts?Member function templates have worked fine as long as I've been around. The only thing you can't have is _virtual_ member function templates. Is making them virtual what you are talking about? --bb
Nov 09 2007
On 11/10/07, Bill Baxter <dnewsgroup billbaxter.com> wrote:Member function templates have worked fine as long as I've been around.Really? The documentation at http://digitalmars.com/d/template.html says: <quote> Templates cannot be used to add non-static members or functions to classes. For example: class Foo { template TBar(T) { T xx; // Error int func(T) { ... } // Error static T yy; // Ok static int func(T t, int y) { ... } // Ok } } Templates cannot be declared inside functions. </quote>The only thing you can't have is _virtual_ member function templates. Is making them virtual what you are talking about?All member functions in D are virtual (unless you explicitly use the "final" keyword). So obviously, yes.
Nov 09 2007
Janice Caron wrote:On 11/10/07, Bill Baxter <dnewsgroup billbaxter.com> wrote:Well, this works (dmd 1.023): ----------- import std.stdio; class Man { void member_function(T)(T arg) { writefln("Got me an x and it's value is %s", x); } int x = 23; } void main() { auto ima = new Man; ima.member_function!(int)(3); } -------------- Seems like the doc is wrong. --bbMember function templates have worked fine as long as I've been around.Really? The documentation at http://digitalmars.com/d/template.html says: <quote> Templates cannot be used to add non-static members or functions to classes. For example: class Foo { template TBar(T) { T xx; // Error int func(T) { ... } // Error static T yy; // Ok static int func(T t, int y) { ... } // Ok } } Templates cannot be declared inside functions. </quote>The only thing you can't have is _virtual_ member function templates. Is making them virtual what you are talking about?All member functions in D are virtual (unless you explicitly use the "final" keyword). So obviously, yes.
Nov 10 2007
On 11/10/07, Bill Baxter <dnewsgroup billbaxter.com> wrote:Well, this works (dmd 1.023):Wow! Well, now I'm confused. If you'd said it works in 2.X, I would have thought "Ooh - Walter's experimenting with a new feature" - but in 1.X? Definitely suggests a documentation change would be in order. (For that matter, all the docs relate to 2.X anyway)
Nov 10 2007
"Janice Caron" wroteOn 11/10/07, Bill Baxter <dnewsgroup billbaxter.com> wrote:Also works in 2.X :)Well, this works (dmd 1.023):Wow! Well, now I'm confused. If you'd said it works in 2.X, I would have thought "Ooh - Walter's experimenting with a new feature" - but in 1.X?Definitely suggests a documentation change would be in order.In fact, the code identified in the document that is an "Error" actually compiles. The results I have found with testing are: - template members variables seem to act like static members of the class - template member functions seem to act like non-virtual member functions of the class (even with override). I think the docs probably should be changed. At least to say Unsupported instead of Error (although I'd much rather see it changed to reflect what actually works :) BTW, given that member templates are supported this way, you can kind of mimic what you want this way: class A { string s; // override in derived classes to alter implementation protected void _s(string t) { s = t;} int f(T)(T t) { _s = toUTF8(t); } // non-virtual function, cannot override } General rule would be: use templates to convert args to what actual members are stored as, use non-template functions to actually interact with members.(For that matter, all the docs relate to 2.X anyway)Click on that D 1.0 link in the upper left, you can get the D 1.0 docs (should be the default IMHO since the default download is D 1.0) -Steve
Nov 10 2007
<quote> Templates cannot be used to add non-static members or functions to classes.I think that's bug 566 from last year: http://d.puremagic.com/issues/show_bug.cgi?id=566
Nov 11 2007
On 11/10/07, Janice Caron <caron800 googlemail.com> wrote:On 11/10/07, Bill Baxter <dnewsgroup billbaxter.com> wrote:When we get the common calling convention whereby f(x) and x.f() are interchangable, then adding non-polymorphic template functions will be a piece of cake. Just declare as f(T)(X x, T t) { ... } and call as x.f(t). Maybe that will be enough. But yeah - I intended to mean "normal" functions. Polymorphic. Virtual.The only thing you can't have is _virtual_ member function templates. Is making them virtual what you are talking about?All member functions in D are virtual (unless you explicitly use the "final" keyword). So obviously, yes.
Nov 09 2007
Janice Caron wrote:On 11/10/07, Janice Caron <caron800 googlemail.com> wrote:I was just about to feature-request virtual templated member functions. I can't mock them, which is one of two major problems in my mocks library. You also can't have a templated method in an interface: interface Collection (T) { void addAll(U : T) (Collection!(U) toAdd); // fail } Which leads to annoyances: "why can't I add all my Bicycles to my Vehicles collection?"On 11/10/07, Bill Baxter <dnewsgroup billbaxter.com> wrote:When we get the common calling convention whereby f(x) and x.f() are interchangable, then adding non-polymorphic template functions will be a piece of cake. Just declare as f(T)(X x, T t) { ... } and call as x.f(t). Maybe that will be enough. But yeah - I intended to mean "normal" functions. Polymorphic. Virtual.The only thing you can't have is _virtual_ member function templates. Is making them virtual what you are talking about?All member functions in D are virtual (unless you explicitly use the "final" keyword). So obviously, yes.
Nov 10 2007
Christopher Wright wrote:Janice Caron wrote:Think about what you're asking for. An interface defines, essentially, a block of vtable addresses and what they mean. So, in a loose sense, interface Foo { void bar(); void baz(); } Says that for any class that implements Foo, there need to be a block of two vtable entries that point to the implementations of bar and baz. Let's try a different interface: interface Quxx { void zyzzy(T)(T); } How many vtable entries is that? There is no sane answer, because it depends on how the interface is used. And not just in one place: any module in the program could alter the number, order and meaning of the vtable block. If this got introduced, single-file compilation would be impossible: you'd need to parse the *entire* program first, and *then* work on generating output. You might say "well, just treat templated methods differently!" The problem then is how exactly *do* you implement them? In order for an interface to work, you need to be able to cast down to it from any implementation. This means the "template" has to be expressible as a run-time pointer or something. But templates are inherently compile-time beasts. Maybe you could return an array of pointers for each instantiation in the implementation, but you still wouldn't be able to guarantee whether a particular instantiation exists or not. If you're going to go down that road, you might as well just give up and go straight for dynamic dispatch, or just pass around Variants. It'll end up about the same. Trust me, there have been a few times I would have *killed* for templates in interfaces. I actually went and wrote my Variant type specifically because I couldn't. :P That said, I don't think this is a restriction that's going to be lifted any time soon. Standard disclaimer: I can always be wrong. Also, it's 1:36 AM right now, which increases those chances. :P -- DanielOn 11/10/07, Janice Caron <caron800 googlemail.com> wrote:I was just about to feature-request virtual templated member functions. I can't mock them, which is one of two major problems in my mocks library. You also can't have a templated method in an interface: interface Collection (T) { void addAll(U : T) (Collection!(U) toAdd); // fail } Which leads to annoyances: "why can't I add all my Bicycles to my Vehicles collection?"On 11/10/07, Bill Baxter <dnewsgroup billbaxter.com> wrote:When we get the common calling convention whereby f(x) and x.f() are interchangable, then adding non-polymorphic template functions will be a piece of cake. Just declare as f(T)(X x, T t) { ... } and call as x.f(t). Maybe that will be enough. But yeah - I intended to mean "normal" functions. Polymorphic. Virtual.The only thing you can't have is _virtual_ member function templates. Is making them virtual what you are talking about?All member functions in D are virtual (unless you explicitly use the "final" keyword). So obviously, yes.
Nov 10 2007
Christopher Wright wrote:Janice Caron wrote:I may be mistaken, but isn't it enough to use the following: ---- interface Collection (T) { void addAll(T) (Collection!(T) toAdd); } ---- a bicycle should conform to a is-a relationship (a bicycle is a vehicle). so you can in fact add them all due to inheritance. or am I missing something here? templates are only useful at compile time. in run time we need to rely on polymorphism (inheritance). Maybe you could give a better example for the case when you need to have template (virtual) member functions? YigalOn 11/10/07, Janice Caron <caron800 googlemail.com> wrote:I was just about to feature-request virtual templated member functions. I can't mock them, which is one of two major problems in my mocks library. You also can't have a templated method in an interface: interface Collection (T) { void addAll(U : T) (Collection!(U) toAdd); // fail } Which leads to annoyances: "why can't I add all my Bicycles to my Vehicles collection?"On 11/10/07, Bill Baxter <dnewsgroup billbaxter.com> wrote:When we get the common calling convention whereby f(x) and x.f() are interchangable, then adding non-polymorphic template functions will be a piece of cake. Just declare as f(T)(X x, T t) { ... } and call as x.f(t). Maybe that will be enough. But yeah - I intended to mean "normal" functions. Polymorphic. Virtual.The only thing you can't have is _virtual_ member function templates. Is making them virtual what you are talking about?All member functions in D are virtual (unless you explicitly use the "final" keyword). So obviously, yes.
Nov 10 2007
Yigal Chripun wrote:I may be mistaken, but isn't it enough to use the following: ---- interface Collection (T) { void addAll(T) (Collection!(T) toAdd); } ---- a bicycle should conform to a is-a relationship (a bicycle is a vehicle). so you can in fact add them all due to inheritance. or am I missing something here?Unfortunately that doesn't quite work. Even if a bicycle is-a vehicle, it doesn't follow that a collection of bicycles is-a collection of vehicles. Consider that you can add a car to a collection of vehicles, but it would be an error to add a car to a collection of bicycles. Thanks, Nathan Reed
Nov 11 2007
On 2007-11-10 01:30:46 -0500, "Janice Caron" <caron800 googlemail.com> said:class A { string s; int f(T)(T t) { s = toUTF8(t); } /* template member function */ alias f!(string) fs; /* explicit instantiation */ alias f!(wstring) fw; /* explicit instantiation */ }Why don't you try `mixin` instead of `alias`? Then I think you can even override them in subclasses, meaning they're made virtual. They're difficult to overload though, at least in D 1.x without overload sets (haven't tried with D 2.0). -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Nov 10 2007
Yigal Chripun Wrote:Christopher Wright wrote:A Collection!(Bicycle) is not a Collection!(Vehicle). You cannot add arbitrary Vehicles to a Collection!(Bicycle), nor can you read arbitrary elements of a Collection!(Vehicle) as Bicycles. You can't cast between the two. So let's say I have Set!(int) called integers and a Set!(long) called longs. In order to add all of the set integers to the set longs, what do I have to do? My fictional Set class defines: void add(T)(T element); void addAll(T) (Set!(T) other); I have to do: foreach (i; integers) longs.add(i);Janice Caron wrote:I may be mistaken, but isn't it enough to use the following: ---- interface Collection (T) { void addAll(T) (Collection!(T) toAdd); } ---- a bicycle should conform to a is-a relationship (a bicycle is a vehicle). so you can in fact add them all due to inheritance. or am I missing something here?On 11/10/07, Janice Caron <caron800 googlemail.com> wrote:I was just about to feature-request virtual templated member functions. I can't mock them, which is one of two major problems in my mocks library. You also can't have a templated method in an interface: interface Collection (T) { void addAll(U : T) (Collection!(U) toAdd); // fail } Which leads to annoyances: "why can't I add all my Bicycles to my Vehicles collection?"On 11/10/07, Bill Baxter <dnewsgroup billbaxter.com> wrote:When we get the common calling convention whereby f(x) and x.f() are interchangable, then adding non-polymorphic template functions will be a piece of cake. Just declare as f(T)(X x, T t) { ... } and call as x.f(t). Maybe that will be enough. But yeah - I intended to mean "normal" functions. Polymorphic. Virtual.The only thing you can't have is _virtual_ member function templates. Is making them virtual what you are talking about?All member functions in D are virtual (unless you explicitly use the "final" keyword). So obviously, yes.templates are only useful at compile time. in run time we need to rely on polymorphism (inheritance).But Set!(int) doesn't inherit from Set!(long). Set!(Object) and Set!(MyClass) are entirely unrelated. There's no polymorphism here.Maybe you could give a better example for the case when you need to have template (virtual) member functions? YigalI'm not sure I ever *need* them, but they'd be quite convenient. Of course, for me, I want them for my mocks library: it's a large collection of final methods, and I don't currently have a way of mocking final methods.
Nov 10 2007