Thread overview
What am I doing wrong here?
May 06, 2022
JG
May 06, 2022
Ali Çehreli
May 06, 2022
JG
May 07, 2022
Salih Dincer
May 08, 2022
JG
May 06, 2022

This isn't code to be used for anything (just understanding).

import std;

struct Delegate(A,B) {
    B function(void* ptr, A a) f;
    void* data;
    B opCall(A a) {
        return f(data,a);
    }
}

auto toDelegate(A, B,S)(S s) {
    static B f(void* ptr, A a) {
        return (*(cast(S*) ptr))(a);
    }
    Delegate!(A,B) ret;
    ret.f=&f;
    ret.data= cast(void*) &s;
    return ret;
}

struct Adder {
    int a;
    int opCall(int b) { return a+b; }
}
auto adder(int a) {
    auto ret = Adder.init;
    ret.a=a;
    return ret;
}

void main() {
    auto g = adder(5);
    g(5).writeln;
    auto d = toDelegate!(int, int)(g);
    d(5).writeln;
    auto a =7;
    auto h = (int b)=>a+b;
    auto d1 = toDelegate!(int,int)(h);
    void* ptr = cast(void*) &h;
    (*cast(int delegate(int)*) ptr)(10).writeln;
    d1(10).writeln;
    h(10).writeln;
}
May 06, 2022
On 5/6/22 11:04, JG wrote:
> This isn't code to be used for anything (just understanding).

This is a segmentation fault. Reduced:

import std;

struct Delegate(A,B) {
    B function(void* ptr, A a) f;
    void* data;
    B opCall(A a) {
        return f(data,a);
    }
}

auto toDelegate(A, B,S)(S s) {
    static B f(void* ptr, A a) {
        return (*(cast(S*) ptr))(a);
    }
    Delegate!(A,B) ret;
    ret.f=&f;
    ret.data= cast(void*) &s;
    return ret;
}

void main() {
    auto a =7;
    auto h = (int b)=>a+b;
    auto d1 = toDelegate!(int,int)(h);
    d1(10);
}

This is what I did to figure out:

1) Compiled with -g

2) Started gdb (my compiled program is 'deneme'):

$ gdb --args ./deneme

3) Entered 'run' in gdb

You are storing the address of the local variable 's' here:

    ret.data= cast(void*) &s;

One good news is, compiling with -dip1000 catches this mistake. :)

Another solution is to pass 's' by ref, in which case you have to make sure that variable lives long enough when its used.

//                      vvv
auto toDelegate(A, B,S)(ref S s) {
  // ...
}

Further, you can mix -dip1000 and ref if you protect the code by also adding 'return' to the parameter:

//                      vvvvvvvvvv
auto toDelegate(A, B,S)(return ref S s) {
  // ...
}

I am surprised that 'in' does not provide similar protection.

//                      vv
auto toDelegate(A, B,S)(in S s) {

The code compiles but crashes. (?)

Ali

May 06, 2022
On Friday, 6 May 2022 at 18:35:40 UTC, Ali Çehreli wrote:
> On 5/6/22 11:04, JG wrote:
> > [...]
>
> This is a segmentation fault. Reduced:
>
> import std;
>
> [...]

Hi, thanks. That was quite silly. (I was thinking the variable lives to the end of  scope of main but not thinking about that I am passing by value).
May 07, 2022

On Friday, 6 May 2022 at 18:04:13 UTC, JG wrote:

>
//...
struct Adder {
    int a;
    int opCall(int b) { return a+b; }
}
auto adder(int a) {
    auto ret = Adder.init;
    ret.a=a;
    return ret;
}

void main() {
    auto g = adder(5);
    g(5).writeln; // 10
    auto d = toDelegate!(int, int)(g);
    d(5).writeln; // 10
// ...
}

The value returned by the delegate structure in the above line is 10. Its parameter is 5, but if you do it to 21, you will get 42. So it doesn't have the ability to delegate Adder.

In summary, the sum function isn't executing. Instead, its value gets double.

SDB@79

May 08, 2022

On Saturday, 7 May 2022 at 02:29:59 UTC, Salih Dincer wrote:

>

On Friday, 6 May 2022 at 18:04:13 UTC, JG wrote:

>
//...
struct Adder {
    int a;
    int opCall(int b) { return a+b; }
}
auto adder(int a) {
    auto ret = Adder.init;
    ret.a=a;
    return ret;
}

void main() {
    auto g = adder(5);
    g(5).writeln; // 10
    auto d = toDelegate!(int, int)(g);
    d(5).writeln; // 10
// ...
}

The value returned by the delegate structure in the above line is 10. Its parameter is 5, but if you do it to 21, you will get 42. So it doesn't have the ability to delegate Adder.

In summary, the sum function isn't executing. Instead, its value gets double.

SDB@79

What do you mean?

import std;

struct Delegate(A,B) {
    B function(void* ptr, A a) f;
    void* data;
    B opCall(A a) {
        return f(data,a);
    }
}

auto toDelegate(A, B,S)(ref S s) {
    static B f(void* ptr, A a) {
        return (*(cast(S*) ptr))(a);
    }
    Delegate!(A,B) ret;
    ret.f=&f;
    ret.data= cast(void*) &s;
    return ret;
}

struct Adder {
    int a;
    int opCall(int b) { return a+b; }
}
auto adder(int a) {
    auto ret = Adder.init;
    ret.a=a;
    return ret;
}

void main() {
    auto g = adder(5);
    g(5).writeln;
    auto d = toDelegate!(int, int)(g);
    d(41).writeln;
    auto a =7;
    auto h = (int b)=>a+b;
    auto d1 = toDelegate!(int,int)(h);
    void* ptr = cast(void*) &h;
    (*cast(int delegate(int)*) ptr)(10).writeln;
    d1(21).writeln;
    h(32).writeln;
}

Output:
10
46
17
28
39

Which is what is expected.