Thread overview
Associative Array & different template types
Jul 03, 2019
Robert M. Münch
Jul 03, 2019
ag0aep6g
Jul 04, 2019
Robert M. Münch
July 03, 2019
I have something like:

template myStruct(T){
	auto makeMyStruct(T,E)(T context, void delegate(E) myFunc){
		static struct myObject {
			this(T context, void delegate(E) myFunc){
				_context = context;
				_myFunc = myFunc;
			}

			private:
				void delegate(E) _myFunc;
				T _context;
		}
	}
}

class myClass {
	void myClassFunc();
}

myClass mc = new myClass;

auto mo = makeMyStruct!myClass(mc, &mc.myClassFunc); // mo = myObject

So, I need to carry around the object from which a delegate was created from because it's not possible to query the delegate for the object later somewhere else in the code.

Now, I want to keep several of the makeMyStruct!... created objects in an AA (or an other container) so that I can compare them with an object pointer. Like this (not working code, just pseudo code):


myObject[string] myObjectArray;

auto mo1 = makeMyStruct!myClassA(mcA, &mcA.myClassFunc); // mo1 = myObject
auto mo2 = makeMyStruct!myClassB(mcB, &mcA.myClassFunc); // mo2 = myObject

myObjectArray["1"] = mo1;
myObjectArray["2"] = mo2;

assert(mcA == mo1._context)
assert(mcA == myObjectArray["1"]._context)


I hope the idea is understandable. Of course this doesn't work because myObjectArray needs a template, which creates different types. But with different types I can't throw everything into on array. May claases, and inheritance from a non-template base type help here?

I would like to keep it as simple as possible...

-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster

July 03, 2019
On 03.07.19 20:20, Robert M. Münch wrote:
> So, I need to carry around the object from which a delegate was created from because it's not possible to query the delegate for the object later somewhere else in the code.

It is possible to get the context object out of a delegate:

----
class C { void method() {} }
void main()
{
    auto c = new C;
    void delegate() dg = &c.method;
    assert(cast(C) dg.ptr is c); /* passes */
}
----

You just have to know (or carry around) the type so that you can cast correctly.

[...]
> myObject[string] myObjectArray;
> 
> auto mo1 = makeMyStruct!myClassA(mcA, &mcA.myClassFunc); // mo1 = myObject
> auto mo2 = makeMyStruct!myClassB(mcB, &mcA.myClassFunc); // mo2 = myObject
> 
> myObjectArray["1"] = mo1;
> myObjectArray["2"] = mo2;
> 
> assert(mcA == mo1._context)
> assert(mcA == myObjectArray["1"]._context)

class MyClassA { void myClassFunc() {} }
class MyClassB { void myClassFunc() {} }

void main()
{
    void delegate()[string] myDelegateArray;

    auto mcA = new MyClassA;
    auto mcB = new MyClassB;

    auto dg1 = &mcA.myClassFunc;
    auto dg2 = &mcB.myClassFunc;

    myDelegateArray["1"] = dg1;
    myDelegateArray["2"] = dg2;

    assert(mcA is cast(MyClassA) dg1.ptr); /* passes */
    assert(mcA is cast(MyClassA) myDelegateArray["1"].ptr); /* passes */

    /* When void* is good enough, you can use .ptr without a cast: */
    assert(dg2.ptr is myDelegateArray["2"].ptr); /* passes */
}
July 04, 2019
On 2019-07-03 19:07:10 +0000, ag0aep6g said:

> On 03.07.19 20:20, Robert M. Münch wrote:
>> So, I need to carry around the object from which a delegate was created from because it's not possible to query the delegate for the object later somewhere else in the code.
> 
> It is possible to get the context object out of a delegate:
> 
> ----
> class C { void method() {} }
> void main()
> {
>      auto c = new C;
>      void delegate() dg = &c.method;
>      assert(cast(C) dg.ptr is c); /* passes */
> }
> ----
> 
> You just have to know (or carry around) the type so that you can cast correctly.

Hmm... IIRC I once played around and it didn't work... seems I messed this up. Thanks for correcting my wrong perception here.

-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster