Okay, let's start with the code to reproduce, to put things in context:
-----
import std.meta : Filter;
import std.typecons : No;
import std.traits : hasUDA;
struct S
{
int a;
int b;
@(No.Wanted) int c;
}
private template isWanted(alias field) {
enum isWanted = !hasUDA!(field, No.Wanted);
}
void foo(TS...)(TS args)
{
import std.conv : to;
import std.stdio : writefln;
foreach (index, arg; args)
{
writefln("%d: %s", index, arg.to!string);
}
}
void main()
{
S s = S(5, 6, 7);
foo(s.tupleof); // works, passes all struct fields as arguments
foo(Filter!(isWanted, s.tupleof)); // error
}
-----
EXPECTED BEHAVIOR
The both calls to foo() work, and the program outputs:
0: 5
1: 6
2: 7
0: 5
1: 6
ACTUAL BEHAVIOR
Compilation fails with the following errors:
tupleof_filter.d(31): Error: need 'this' for 'a' of type 'int'
tupleof_filter.d(31): Error: need 'this' for 'b' of type 'int'
REAL WORLD CASE
I hit this while working on https://github.com/trishume/ddbus/pull/21, specifically when trying to allow selective marshaling of struct fields. I changed https://github.com/thaven/ddbus/blob/6bce6cf6490ce819f048b7ea8f1458ec66fbf1c8/source/ddbus/conv.d#L119 (which worked) from
buildIter(&sub, arg.tupleof);
to
buildIter(&sub, Filter!(isAllowedField, arg.tupleof));
and added the isAllowedField predicate template and then got the 'no this for member' errors. I needed to rewrite this nice compact line of code into ugly `foreach` + `static if` to work around the issue.
Comment #1 by robert.schadek — 2024-12-13T18:53:40Z