www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Coreect way to create delegate for struct method.

reply Andrey <saasecondbox yandex.ru> writes:
Hello,
This is a code:
import std.stdio;

struct Test
{
    static Test opCall()
    {
        Test test;
        test.handler = &test.one;
 
        return test;
    }
 
    void one() const { writeln("In handler: Address = ", &this, 
 "; Text = ", text); }
 
    void execute()
    {
        text = "Inited!";
        writeln("Before: Address = ", &this, "; Text = ", text);
        handler();
    }
 
    void delegate() const handler = void;
    string text = "NoValue";
}

struct Qwerty
{
    void prepare()
    {
        _test = Test();
    }
 
    void execute()
    {
        _test.execute();
    }
 
private:
    Test _test  = void;
}

void main()
{
    Qwerty qwerty;
    qwerty.prepare();
    qwerty.execute();
}
Here I try to make a delegate for struct "Test" and method "one()". When I launch it then I get this output:
Before: Address = 7FFC096A2C20; Text = Inited!
In handler: Address = 7FFC096A2BE8; Text = NoValue
It means that my delegate captures one object of Test, but in place of call uses another... I want just to save my method into variable and after that use it on some arbitrary object of type "Test". How to do it in D? In C++ it is very easy:
 test.handler = &Test::one;
and call:
 (this->*handler)();
or
 (someTestObjPtr->*handler)();
I know axactly that in the first variant a context will be "this", and in the second - "someTestObjPtr".
Aug 21 2018
next sibling parent reply Alex <sascha.orlov gmail.com> writes:
On Tuesday, 21 August 2018 at 21:29:38 UTC, Andrey wrote:
 Hello,
 This is a code:
import std.stdio;

struct Test
{
    static Test opCall()
    {
        Test test;
        test.handler = &test.one;
 
        return test;
    }
 
    void one() const { writeln("In handler: Address = ", &this, 
 "; Text = ", text); }
 
    void execute()
    {
        text = "Inited!";
        writeln("Before: Address = ", &this, "; Text = ", text);
        handler();
    }
 
    void delegate() const handler = void;
    string text = "NoValue";
}

struct Qwerty
{
    void prepare()
    {
        _test = Test();
    }
 
    void execute()
    {
        _test.execute();
    }
 
private:
    Test _test  = void;
}

void main()
{
    Qwerty qwerty;
    qwerty.prepare();
    qwerty.execute();
}
Here I try to make a delegate for struct "Test" and method "one()". When I launch it then I get this output:
Before: Address = 7FFC096A2C20; Text = Inited!
In handler: Address = 7FFC096A2BE8; Text = NoValue
It means that my delegate captures one object of Test, but in place of call uses another... I want just to save my method into variable and after that use it on some arbitrary object of type "Test". How to do it in D? In C++ it is very easy:
 test.handler = &Test::one;
and call:
 (this->*handler)();
or
 (someTestObjPtr->*handler)();
I know axactly that in the first variant a context will be "this", and in the second - "someTestObjPtr".
Maybe, like this: ´´´ import std.stdio; struct Test { static auto opCall() { auto test = new Test(); test.handler = &test.one; return test; } void one() const { writeln("In handler: Address = ", &this, "; Text = ", text); } void execute() { text = "Inited!"; writeln("Before: Address = ", &this, "; Text = ", text); handler(); } void delegate() const handler = void; string text = "NoValue"; } struct Qwerty { void prepare() { _test = Test(); } void execute() { _test.execute(); } private: Test* _test = void; } void main() { Qwerty qwerty; qwerty.prepare(); qwerty.execute(); } ´´´
Aug 21 2018
parent reply Andrey <saasecondbox yandex.ru> writes:
On Tuesday, 21 August 2018 at 22:52:31 UTC, Alex wrote:
 Maybe, like this:
Thank you but here you use heap to create ab object. I want only on stack. I know that one can do this:
 test_handler.ptr = null;
and in place of call this:
handler.ptr = cast(void*)&this;
but it is ugly... Hmm, any other ideas?
Aug 22 2018
next sibling parent Alex <sascha.orlov gmail.com> writes:
On Wednesday, 22 August 2018 at 07:03:02 UTC, Andrey wrote:
 On Tuesday, 21 August 2018 at 22:52:31 UTC, Alex wrote:
 Maybe, like this:
Thank you but here you use heap to create ab object. I want only on stack. I know that one can do this:
 test_handler.ptr = null;
and in place of call this:
handler.ptr = cast(void*)&this;
but it is ugly... Hmm, any other ideas?
Ok... Another try: ´´´ import std.stdio; struct Test { void opAssign(Test) { "performing assignment".writeln; this.handler = &(this.one); } void one() const { writeln("In handler: Address = ", &this, "; Text = ", text); } void execute() { text = "Inited!"; writeln("Before: Address = ", &this, "; Text = ", text); handler(); } void delegate() handler = void; string text = "NoValue"; } struct Qwerty { void prepare() { _test = Test(); } void execute() { _test.execute(); } private: Test _test = void; } void main() { Qwerty qwerty; qwerty.prepare(); qwerty.execute(); } ´´´
Aug 22 2018
prev sibling parent Kagamin <spam here.lot> writes:
On Wednesday, 22 August 2018 at 07:03:02 UTC, Andrey wrote:
 but it is ugly...
You can write a type that will hide it.
Aug 22 2018
prev sibling parent Rene Zwanenburg <renezwanenburg gmail.com> writes:
On Tuesday, 21 August 2018 at 21:29:38 UTC, Andrey wrote:
 Hello,
 This is a code:
        (...)
        test.handler = &test.one;
That's an internal pointer, and internal pointers are not allowed in structs precisely because of the issues you're running into: the pointer will be invalid after a move. You may be able to get it kind of working, but I'd recommend looking for another solution to your problem. This is one of those things that will come back to bite you later.
Aug 22 2018