[Template] Mixins and foreach

Jonathan M Davis newsgroup.d at jmdavisprog.com
Sun Oct 1 04:44:16 UTC 2017


On Sunday, October 01, 2017 03:11:15 Nicholas Wilson via Digitalmars-d-learn 
wrote:
> On Sunday, 1 October 2017 at 02:29:57 UTC, Jonathan M Davis wrote:
> > I would have thought that it would be pretty straightforward to
> > just write a recursive, eponymous template to solve the problem
> > and have it recursively build a single string to mix in for
> > everything.
> >
> > In general though, without static foreach, you're either going
> > to be using templates to operate in a functional manner rather
> > than a procedural one, or you're going to be writing procedural
> > code that generates a string to mix in. The latter doesn't
> > really work though when the arguments are an AliasSeq of fields
> > like you get from tupleof.
> >
> > This looks like it would be pretty straightforward to do with a
> > recursive template though.
> >
> > - Jonathan M Davis
>
> I think I've almost got it:
>
> string generateGetInfo( /*alias*/ Info,alias func,args...)()
> {
>      string code;
>      foreach(field; AliasSeq!(Info.tupleof))
>      {
>          code ~= "@property " ~ typeof(field).stringof ~ " " ~
> field.stringof ~ "()" ~
>                  "{ " ~
>                  "    typeof(return) ret;" ~
>                  func.stringof ~ "(" ~ args.stringof ~ "," ~
> __traits(getAttributes, field).stringof ~
> ",ret.sizeof,&ret,null);" ~
>                  "return ret; " ~
>                  "}";
>          }
>      }
>      return code;
> }
> struct MyType
> {
>      void* raw;
>      static struct Info
>      {
>          @(42) int foo;
>      }
>      mixin(generateGetInfo!(Info,MyTypeGetInfo,raw));//errors out
>      pragma(msg,generateGetInfo!(Info,MyTypeGetInfo,raw)); // also
> errors out
> }
> but this gives a bunch of
>
>      Error: need 'this' for 'foo' of type 'int'.
>
> even with the pragma msg.
> I dont see why though:
>      a) the Info struct is static
>      b) I'm only using .stringof on the _type's_ fields
>      c) its got the name in the errors message! it just wont let
> me use it.
>
> > The latter doesn't really work though when the arguments are an
> > AliasSeq of fields like you get from tupleof.
>
> Why is that and is that what is causing the problem here?

Well, what I meant was that you can't pass fields as function arguments,
which is generally what you do with a function that's generating a string
mixin, and if you pass the fields as template arguments, then you tend to be
restricted in the ways that you're normally restricted with compile-time
stuff, which means no procedural code. However, you can use foreach with an
AliasSeq in the fashion that you're doing, which should work and give you
some level of procedural code in spite of the fact that you're dealing with
compile-time stuff. The explicit AliasSeq should not be necessary, since the
tupleof already is one, but it shouldn't matter either way, since AliasSeqs
automatically expand (one of the reasons that calling them tuples is a poor
idea).

I would note that the static on Info should have zero effect. It would
matter if Info were declared inside of a function, and IIRC, it would matter
when declaring a class inside a class, but I don't believe that it has any
effect when declaring a struct inside a struct. Such structs aren't
associated with the struct that they're in aside from namespacing. It's
required in the case of nested classes, because otherwise, they get access
to the class that they're in and are associated with an instance of it, and
it's required for structs and classes in functions in order to indicate that
they don't have access to the function's variables. But nothing like that is
happening with a struct inside a struct.

I don't see any reason why the compiler would be complaining about 'this'
being required. I would think that that would imply that the compiler thinks
that you're accessing the member rather than introspecting on it. The fact
that you're passing raw to generateGetInfo does seem off though, since it
wouldn't be accessible at compile time. I would have expected that to result
in a compilation errero, but if it's complaining about 'this' when accessing
foo rather than complaining about raw, then that implies that raw isn't the
problem - or at least not that problem.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list