Re: Virtual methods on stack objects

2022-05-12 Thread vit via Digitalmars-d-learn

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:

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 copying

Great!

> 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


Yeah, but you can't return `Cat` . And the documentation for 
`scoped` says:
It'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.


`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

}
```


Re: Virtual methods on stack objects

2022-05-11 Thread dangbinghoo via Digitalmars-d-learn

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:

[...]


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.


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 !)
```



Re: Virtual methods on stack objects

2022-05-11 Thread Marvin Hannott via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 20:23:07 UTC, Ali Çehreli wrote:

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 copying

Great!

> 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


Yeah, but you can't return `Cat` . And the documentation for 
`scoped` says:
It'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.


Re: Virtual methods on stack objects

2022-05-11 Thread Ali Çehreli via Digitalmars-d-learn

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 copying

Great!

> 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



Re: Virtual methods on stack objects

2022-05-11 Thread Marvin Hannott via Digitalmars-d-learn

On Wednesday, 11 May 2022 at 14:44:59 UTC, Ali Çehreli wrote:

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


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.


Re: Virtual methods on stack objects

2022-05-11 Thread Ali Çehreli via Digitalmars-d-learn

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



Virtual methods on stack objects

2022-05-11 Thread Marvin Hannott via Digitalmars-d-learn

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?