DMD is of two minds when invoking opDispatch inside WithStatements, and requires that the template be possible to instantiate with the arguments passed, followed by instatiating it with an empty parameter tuple:
unittest {
with (S1.init) {
a(1); // Compiles
}
with (S2.init) {
a(1); // is not callable using argument types (int)
}
}
struct S1 {
auto opDispatch(string name, Args...)(Args args) {
static assert(Args.length == 0);
return (int i){};
}
}
struct S2 {
auto opDispatch(string name)() {
return (int i){};
}
}
As the example with S2 shows, the compiler complains when opDispatch takes no parameters (this is sensible). However, as S1 shows, Args is actually empty when opDispatch is instantiated, and instead opDispatch needs to return a lambda that actually handles the run-time arguments (this is not sensible, on more than one level).
The correct behavior would of course be for this to compile and run:
unittest {
with (S3.init) {
a(1);
}
}
struct S3 {
auto opDispatch(string name, Args...)(Args args) {
static assert(Args.length == 1);
static assert(is(Args[0] == int));
assert(args[0] == 1);
}
}
Comment #1 by robert.schadek — 2024-12-13T19:03:36Z