digitalmars.D.learn - Virtual methods on stack objects
- Marvin Hannott (5/5) May 11 2022 Hi everybody!
- =?UTF-8?Q?Ali_=c3=87ehreli?= (9/12) May 11 2022 Problems classes solve don't usually need copying nor need to be on the
- Marvin Hannott (7/23) May 11 2022 I appreciate the answer, don't much like the "solutions".
- =?UTF-8?Q?Ali_=c3=87ehreli?= (36/39) May 11 2022 Great!
- Marvin Hannott (37/79) May 11 2022 Yeah, but you can't return `Cat` 😉. And the documentation for
- dangbinghoo (18/58) May 11 2022 add a single `writeln("A.f")` to A.f and `writeln("B.f")` B.f,
- vit (33/131) May 12 2022 `scoped` is not necesary, try this:
Hi everybody! I understand that D's classes solve some particular problems. However, they also cause problems because they cannot be copied when scoped. So how do I get virtual methods on a copyable stack object?
May 11 2022
On 5/11/22 06:57, Marvin Hannott wrote:I understand that D's classes solve some particular problems. However, they also cause problems because they cannot be copied when scoped. So how do I get virtual methods on a copyable stack object?Problems classes solve don't usually need copying nor need to be on the stack. Is that really necessary? If so, I can think of two solutions: a) Use a struct but provide "virtual" functions manually (with function pointers like one would do in C, all of which potentially collected in a per-type function table (a.k.a. vtbl :) )). b) Use classes but provide a virtual function that you call to copy. Ali
May 11 2022
On Wednesday, 11 May 2022 at 14:44:59 UTC, Ali Çehreli wrote:On 5/11/22 06:57, Marvin Hannott wrote:I appreciate the answer, don't much like the "solutions". It's not so much about copying, but about heap allocations. Tying virtual methods to heap allocation is kind of unfortunate. And I am not really keen on building a poor man's vtbl. And for my taste, scoped class objects should have value semantics.I understand that D's classes solve some particular problems.However,they also cause problems because they cannot be copied whenscoped. Sohow do I get virtual methods on a copyable stack object?Problems classes solve don't usually need copying nor need to be on the stack. Is that really necessary? If so, I can think of two solutions: a) Use a struct but provide "virtual" functions manually (with function pointers like one would do in C, all of which potentially collected in a per-type function table (a.k.a. vtbl :) )). b) Use classes but provide a virtual function that you call to copy. Ali
May 11 2022
On 5/11/22 13:06, Marvin Hannott wrote:I appreciate the answer, don't much like the "solutions".Me neither. :)It's not so much about copyingGreat!scoped class objects should have value semantics.std.typecons.scoped does exactly that: https://dlang.org/phobos/std_typecons.html#scoped import std.stdio; import std.typecons; interface Animal { string sing(); } class Cat : Animal { this() { writeln("Hi!"); } ~this() { writeln("Bye!"); } string sing() { return "mew"; } } void foo(Animal animal) { writeln(animal.sing()); } void bar() { auto cat = scoped!Cat(); foo(cat); } void main() { bar(); } The output: Hi! mew Bye! Ali
May 11 2022
On Wednesday, 11 May 2022 at 20:23:07 UTC, Ali Çehreli wrote:On 5/11/22 13:06, Marvin Hannott wrote:Yeah, but you can't return `Cat` 😉. And the documentation for `scoped` says:I appreciate the answer, don't much like the "solutions".Me neither. :)It's not so much about copyingGreat!scoped class objects should have value semantics.std.typecons.scoped does exactly that: https://dlang.org/phobos/std_typecons.html#scoped import std.stdio; import std.typecons; interface Animal { string sing(); } class Cat : Animal { this() { writeln("Hi!"); } ~this() { writeln("Bye!"); } string sing() { return "mew"; } } void foo(Animal animal) { writeln(animal.sing()); } void bar() { auto cat = scoped!Cat(); foo(cat); } void main() { bar(); } The output: Hi! mew Bye! AliIt's illegal to move a class instance even if you are sure there are no pointers to it. As such, it is illegal to move a scoped object.That's kinda very limiting. Anyway, I cooked up another idea based on your first suggestions. ```D struct S { static private interface I { int f(int i); } static private final class A : I { int f(int i) {return i;} } static private final class B : I { int f(int i) {return i+ 1;} } private I i; private int d; this(int d) { this.d = d; if(d < 10) { i = scoped!A(); }else { i = scoped!B(); } } int f() { return i.f(d);} } ``` I mean, this is a super dumb example, but it kinda works. And I think it could be made a lot less tedious with some mixin magic.
May 11 2022
On Wednesday, 11 May 2022 at 20:53:21 UTC, Marvin Hannott wrote:On Wednesday, 11 May 2022 at 20:23:07 UTC, Ali Çehreli wrote:add a single `writeln("A.f")` to A.f and `writeln("B.f")` B.f, and a simple test ```d void main() { S s1 = S(9); S s2 = S(12); s1.f(); s2.f(); } ``` outputs: ``` A.f Error: program killed by signal 11 (Aka. segmentation fault !) ```[...]Yeah, but you can't return `Cat` 😉. And the documentation for `scoped` says:[...]That's kinda very limiting. Anyway, I cooked up another idea based on your first suggestions. ```D struct S { static private interface I { int f(int i); } static private final class A : I { int f(int i) {return i;} } static private final class B : I { int f(int i) {return i+ 1;} } private I i; private int d; this(int d) { this.d = d; if(d < 10) { i = scoped!A(); }else { i = scoped!B(); } } int f() { return i.f(d);} } ``` I mean, this is a super dumb example, but it kinda works. And I think it could be made a lot less tedious with some mixin magic.
May 11 2022
On Wednesday, 11 May 2022 at 20:53:21 UTC, Marvin Hannott wrote:On Wednesday, 11 May 2022 at 20:23:07 UTC, Ali Çehreli wrote:`scoped` is not necesary, try this: ```d import std.typecons; struct S{ static private interface I{ int f(int i)const; } static private final class A : I{ static immutable typeof(this) instance = new immutable typeof(this)(); int f(int i)const {return i;} } static private final class B : I{ static immutable typeof(this) instance = new immutable typeof(this)(); int f(int i)const {return i+ 1;} } private immutable I i; private int d; this(int d){ this.d = d; if(d < 10) i = A.instance; else i = B.instance; } int f() { return i.f(d);} } void main(){ import std.stdio; S(1).f().writeln(); /// 1 S(100).f().writeln(); /// 101 } ```On 5/11/22 13:06, Marvin Hannott wrote:Yeah, but you can't return `Cat` 😉. And the documentation for `scoped` says:I appreciate the answer, don't much like the "solutions".Me neither. :)It's not so much about copyingGreat!scoped class objects should have value semantics.std.typecons.scoped does exactly that: https://dlang.org/phobos/std_typecons.html#scoped import std.stdio; import std.typecons; interface Animal { string sing(); } class Cat : Animal { this() { writeln("Hi!"); } ~this() { writeln("Bye!"); } string sing() { return "mew"; } } void foo(Animal animal) { writeln(animal.sing()); } void bar() { auto cat = scoped!Cat(); foo(cat); } void main() { bar(); } The output: Hi! mew Bye! AliIt's illegal to move a class instance even if you are sure there are no pointers to it. As such, it is illegal to move a scoped object.That's kinda very limiting. Anyway, I cooked up another idea based on your first suggestions. ```D struct S { static private interface I { int f(int i); } static private final class A : I { int f(int i) {return i;} } static private final class B : I { int f(int i) {return i+ 1;} } private I i; private int d; this(int d) { this.d = d; if(d < 10) { i = scoped!A(); }else { i = scoped!B(); } } int f() { return i.f(d);} } ``` I mean, this is a super dumb example, but it kinda works. And I think it could be made a lot less tedious with some mixin magic.
May 12 2022