Created
May 15, 2018 21:11
-
-
Save run-dlang/18845c9df3d73e45c945feaccfebfcdc to your computer and use it in GitHub Desktop.
Code shared from run.dlang.io.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import std.stdio; | |
class SomeClass | |
{ | |
void memberFunc(int x, float y) | |
{ | |
writeln("SomeClass.memberFunc(", x, ", ", y, ")"); | |
} | |
} | |
struct SomeStruct | |
{ | |
void memberFunc(int x, float y) | |
{ | |
writeln("SomeStruct.memberFunc(", x, ", ", y, ")"); | |
} | |
} | |
void notMemberFunc1(SomeClass s, int x, float y) | |
{ | |
s.memberFunc(x, y); | |
} | |
void notMemberFunc2(SomeStruct* s, int x, float y) | |
{ | |
s.memberFunc(x, y); | |
} | |
auto makeDelegate(alias fun, T)(T obj) | |
if (is(T == class)) | |
{ | |
void delegate(int, float) result; | |
static class Shim : T | |
{ | |
final void fwd(int x, float y) { return fun(this, x, y); } | |
} | |
result.ptr = cast(void*) obj; | |
result.funcptr = cast(void function(int, float)) &Shim.fwd; | |
return result; | |
} | |
auto makeDelegate(alias fun, T)(T* obj) | |
if (is(T == struct)) | |
{ | |
void delegate(int, float) result; | |
static struct Shim | |
{ | |
void fwd(int x, float y) { fun(cast(T*) &this, x, y); } | |
} | |
result.ptr = obj; | |
result.funcptr = cast(void function(int, float)) &Shim.fwd; | |
return result; | |
} | |
void main() | |
{ | |
auto x = new SomeClass; | |
auto y = makeDelegate!notMemberFunc1(x); | |
y(41, 42); | |
auto z = new SomeStruct; | |
y = makeDelegate!notMemberFunc2(z); | |
y(43, 44); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Mike Parker sent me an email that indicated this code "makes no additional alocations or indirections". However, this is not the case. The code inside the
fwd
function is an indirection, a chunk of code that MUST exist at runtime in order to forward the a call to a delegate function to the real function being called. In fact, since you have defined the functionsnonMemberFunc1
andnonMemberFunc2
as normal functions, you will always have to create a "conversion" function to forward a delegate call to the actual function. In order for a library solution to not introduce "indirection", you'll need to modify the function definition itself so that it matches the delegate ABI. The only way to do this currently is to define those functions inside a dummy struct/class.