This feels like a natural extension to existing semantics. It
doesn't require new syntax and serves as a solution to some
issues when working with delegates.
Say some API wants a delegate like this: void delegate(string arg)
With this feature, you could take a function like this:
void myCoolFunction(MyClassObject obj, string arg)
{
// ...
}
and the following would have the same delegate type:
&myClassObject.myCoolFunction // type is void delegate(string arg)
This of course wouldn't work for all functions. The first
parameter of the function would need to have the same calling
convention as the "this" parameter for a "delegate".
void cantBecomeDelegate(SomeBigStructType s)
{
}
&myStruct.cantBecomeDelegate // Error
error: cannot convert UFCS call to delegate because the first
parameter of function 'cantBecomeDelegate' is too large.
Consider adding "ref" to the first parameter or making it a
pointer.
To fix this you could do something like this:
void canBecomeDelegate(ref SomeBigStructType s)
{
}
&myStruct.canBecomeDelegate // OK!

This feels like a natural extension to existing semantics. It
doesn't require new syntax and serves as a solution to some
issues when working with delegates.
Say some API wants a delegate like this: void delegate(string
arg)
With this feature, you could take a function like this:
void myCoolFunction(MyClassObject obj, string arg)
{
// ...
}
and the following would have the same delegate type:
&myClassObject.myCoolFunction // type is void delegate(string
arg)
This of course wouldn't work for all functions. The first
parameter of the function would need to have the same calling
convention as the "this" parameter for a "delegate".
void cantBecomeDelegate(SomeBigStructType s)
{
}
&myStruct.cantBecomeDelegate // Error
error: cannot convert UFCS call to delegate because the first
parameter of function 'cantBecomeDelegate' is too large.
Consider adding "ref" to the first parameter or making it a
pointer.
To fix this you could do something like this:
void canBecomeDelegate(ref SomeBigStructType s)
{
}
&myStruct.canBecomeDelegate // OK!

What would be the usage of this ?
Actually i think i see the ABI trick you want to use. And it
works:
==================
import std.stdio;
alias ProtoD = void delegate(size_t);
alias ProtoF = void function(size_t);
class Foo{size_t a;}
extern(C) void pseudoMemberFunc(Foo foo, size_t a)
{ foo.a = a;}
void main()
{ Foo foo = new Foo;
// under the hood it's what would make
"&foo.pseudoMemberFunc;"
ProtoD dg;
dg.funcptr = cast(ProtoF) &pseudoMemberFunc;
dg.ptr = cast(void*) foo;
// close the hood carefully
dg(42);
writeln(foo.a);
}
It works in extern(C) only because of parameter order.
==================
But:
1/ It's dangerous because then nothing guarantees anymore that
.funcptr is a n actual member function.
2/ Why not just a member function ?

For the same reason that UFCS exists. You can't add "member
functions" to external library types.

Good point. I have to say that this feature then makes me think
to what's called "class helpers" in the Delphi/Object Pascal
world. That's exactly for what they're used.

I've added a DIP for this (https://github.com/dlang/DIPs/pull/61).
At first I first thought that all we needed was to add semantics
to take the address of a UFCS-style call, but after messing
around with your example I realized that delegates are not
ABI-compatible with functions that take the delegate ptr as the
first parameter. You mentioned that the problem was with the
parameter order and that this should work with extern(C)
functions and I think you're right.
The new DIP proposes the addition of "Extension Methods" which
are functions that are ABI-compatible with delegates. You define
an extension method by naming the first parameter "this":
struct Foo
{
void bar(int x)
{
}
}
void baz(ref Foo this, int x)
{
}
Because the first parameter of baz is named this, it is an
"extension method" of Foo which means it is ABI-compatible with
the method bar.
void delegate(int x) dg;
Foo foo;
dg = &foo.bar; // a normal method delegate
dg(42); // calls foo.bar(42)
dg = &foo.baz; // an extension method delegate
dg(42); // calls baz(foo, 42);
dg = &baz; // a "null delegate", unsafe code, funcptr points
to the baz function, but ptr is null
dg(42); // calls baz(null, 42);

I've added a DIP for this
(https://github.com/dlang/DIPs/pull/61).
At first I first thought that all we needed was to add
semantics to take the address of a UFCS-style call, but after
messing around with your example I realized that delegates are
not ABI-compatible with functions that take the delegate ptr as
the first parameter. You mentioned that the problem was with
the parameter order and that this should work with extern(C)
functions and I think you're right.
The new DIP proposes the addition of "Extension Methods" which
are functions that are ABI-compatible with delegates. You
define an extension method by naming the first parameter "this":
[...]

I've added a DIP for this
(https://github.com/dlang/DIPs/pull/61).
At first I first thought that all we needed was to add
semantics to take the address of a UFCS-style call, but after
messing around with your example I realized that delegates are
not ABI-compatible with functions that take the delegate ptr as
the first parameter. You mentioned that the problem was with
the parameter order and that this should work with extern(C)
functions and I think you're right.
The new DIP proposes the addition of "Extension Methods" which
are functions that are ABI-compatible with delegates. You
define an extension method by naming the first parameter "this":
struct Foo
{
void bar(int x)
{
}
}
void baz(ref Foo this, int x)
{
}
Because the first parameter of baz is named this, it is an
"extension method" of Foo which means it is ABI-compatible with
the method bar.
void delegate(int x) dg;
Foo foo;
dg = &foo.bar; // a normal method delegate
dg(42); // calls foo.bar(42)
dg = &foo.baz; // an extension method delegate
dg(42); // calls baz(foo, 42);
dg = &baz; // a "null delegate", unsafe code, funcptr
points to the baz function, but ptr is null
dg(42); // calls baz(null, 42);

I've added a DIP for this
(https://github.com/dlang/DIPs/pull/61).
At first I first thought that all we needed was to add
semantics to take the address of a UFCS-style call, but after
messing around with your example I realized that delegates are
not ABI-compatible with functions that take the delegate ptr
as the first parameter. You mentioned that the problem was
with the parameter order and that this should work with
extern(C) functions and I think you're right.
The new DIP proposes the addition of "Extension Methods" which
are functions that are ABI-compatible with delegates. You
define an extension method by naming the first parameter
"this":
struct Foo
{
void bar(int x)
{
}
}
void baz(ref Foo this, int x)
{
}
Because the first parameter of baz is named this, it is an
"extension method" of Foo which means it is ABI-compatible
with the method bar.
void delegate(int x) dg;
Foo foo;
dg = &foo.bar; // a normal method delegate
dg(42); // calls foo.bar(42)
dg = &foo.baz; // an extension method delegate
dg(42); // calls baz(foo, 42);
dg = &baz; // a "null delegate", unsafe code, funcptr
points to the baz function, but ptr is null
dg(42); // calls baz(null, 42);

Yes I'm familiar with C# extension methods and that was my
initial thought. The one advantage I saw with naming the
parameter "this" was that it produces more "refactorable" code.
If the first parameter of a delegateable function is a reference
to a struct or a class, then you could move the function inside
the struct/class, take out the first parameter and the code will
work as a member function with no changes since the "this"
keyword will be referring to the same object in both cases. But
it's not a big deal, either syntax works fine in my opinion.