Thread overview
Given an object, how to call an alias to a member function on it?
May 02, 2023
Quirin Schroll
May 02, 2023
ag0aep6g
May 03, 2023
Nick Treleaven
May 03, 2023
ag0aep6g
May 03, 2023
Nick Treleaven
May 03, 2023
Adam D Ruppe
May 04, 2023
Quirin Schroll
May 02, 2023

How do I invoke the member function in a reliable way? Given obj of the type of the object, I used mixin("obj.", __traits(identifier, memberFunc), "(params)"), but that has issues, among probably others, definitely with visibility. (The member function alias is a template parameter.)

May 02, 2023
On 02.05.23 14:52, Quirin Schroll wrote:
> How do I invoke the member function in a reliable way? Given `obj` of the type of the object, I used `mixin("obj.", __traits(identifier, memberFunc), "(params)")`, but that has issues, among probably others, definitely with visibility. (The member function alias is a template parameter.)

Construct a delegate from the alias and the object, and call that delegate:

----
class C
{
    int field = 42;
    void method() { import std.stdio; writeln(field); }
}

void fun(alias method)(C c)
{
    void delegate() dg;
    dg.funcptr = &method;
    dg.ptr = cast(void*) c;
    dg();
}

void main()
{
    fun!(C.method)(new C); /* prints "42" */
}
----
May 02, 2023

On 5/2/23 8:52 AM, Quirin Schroll wrote:

>

How do I invoke the member function in a reliable way? Given obj of the type of the object, I used mixin("obj.", __traits(identifier, memberFunc), "(params)"), but that has issues, among probably others, definitely with visibility. (The member function alias is a template parameter.)

Isn't that what __traits(child) is for?

https://dlang.org/spec/traits.html#child

-Steve

May 03, 2023
On Tuesday, 2 May 2023 at 13:06:41 UTC, ag0aep6g wrote:
> void fun(alias method)(C c)
> {
>     void delegate() dg;
>     dg.funcptr = &method;
>     dg.ptr = cast(void*) c;
>     dg();
> }

This also works:

void fun(alias method)(C c)
{
    void delegate() dg = &c.method;
    dg();
}

May 03, 2023
On 03.05.23 13:13, Nick Treleaven wrote:
> On Tuesday, 2 May 2023 at 13:06:41 UTC, ag0aep6g wrote:
>> void fun(alias method)(C c)
>> {
>>     void delegate() dg;
>>     dg.funcptr = &method;
>>     dg.ptr = cast(void*) c;
>>     dg();
>> }
> 
> This also works:
> 
> void fun(alias method)(C c)
> {
>      void delegate() dg = &c.method;
>      dg();
> }
> 

No, it doesn't. You're not using the alias. You're just accessing `c.method` directly. If the actual method weren't called "method", you'd get an error.
May 03, 2023
On Tuesday, 2 May 2023 at 13:57:23 UTC, Steven Schveighoffer wrote:
> Isn't that what `__traits(child)` is for?
>
> https://dlang.org/spec/traits.html#child

Yes, __traits(child, object, method_alias)(args) is the way to do it.
May 03, 2023
On Wednesday, 3 May 2023 at 11:26:00 UTC, ag0aep6g wrote:
> On 03.05.23 13:13, Nick Treleaven wrote:
>> void fun(alias method)(C c)
>> {
>>      void delegate() dg = &c.method;
>>      dg();
>> }
>> 
>
> No, it doesn't. You're not using the alias. You're just accessing `c.method` directly. If the actual method weren't called "method", you'd get an error.

Sorry, you're right.
May 04, 2023

On Wednesday, 3 May 2023 at 11:38:46 UTC, Adam D Ruppe wrote:

>

On Tuesday, 2 May 2023 at 13:57:23 UTC, Steven Schveighoffer wrote:

>

Isn't that what __traits(child) is for?

https://dlang.org/spec/traits.html#child

Yes, __traits(child, object, method_alias)(args) is the way to do it.

This doesn’t work, but a slight modification does the trick:

--- a.d
#line 3 "a.d" // for run.dlang.io

struct S
{
    private void f() {}
}
alias Sf = S.f;

--- b.d
#line 12 "b.d" // for run.dlang.io

import a;

void main()
{
    S s;
    __traits(child, s, Sf)(); // error: Error: struct `a.S` function `f` is not accessible
    (&__traits(child, s, Sf))(); // ok
}

Thanks for making me aware of __traits(child).