www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 17692] New: Filtering a struct instance's .tupleof loses

https://issues.dlang.org/show_bug.cgi?id=17692

          Issue ID: 17692
           Summary: Filtering a struct instance's .tupleof loses contained
                    this reference
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Linux
            Status: NEW
          Severity: enhancement
          Priority: P1
         Component: dmd
          Assignee: nobody puremagic.com
          Reporter: htvennik gmail.com

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.

--
Jul 25