www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Cannot interpret struct at compile time

reply Robert Clipsham <robert octarineparrot.com> writes:
Hey all,

I was wondering if anyone could enlighten me as to why the following 
code does not compile (dmd2, latest release or the beta):
----
struct Foo
{
     int a;
}

string test()
{
         string str = "struct " ~ Foo.stringof ~ "_{";
         foreach (j, f; Foo.tupleof)
         {
             enum fullFieldName = Foo.tupleof[j].stringof;
             str ~= typeof(f).stringof ~ ' ' ~ 
fullFieldName[Foo.stringof.length + 3 .. $];
         }
         return str ~ "}";
}

void main()
{
     mixin(test());
}
----
If fails with the errors:
test.d(9): Error: Cannot interpret Foo at compile time
test.d(19): Error: cannot evaluate test() at compile time
test.d(19): Error: argument to mixin must be a string, not (test())
test.d(19): Error: cannot evaluate test() at compile time
test.d(19): Error: argument to mixin must be a string, not (test())

Thanks,

-- 
Robert
http://octarineparrot.com/
May 07 2011
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Not too sure, CTFE is a pain in the ass sometimes. What exactly are
you trying to do, print field names in a custom way?

I have this piece of code I use for printing values, maybe you can
customize it for own your needs:

import std.stdio;
import std.conv;
import std.algorithm;

struct Foo
{
    int abc;
    int foobar;
}

void printFields(T)(T args)
{
    auto values = args.tupleof;

    size_t max;
    size_t temp;
    foreach (index, value; values)
    {
        temp = T.tupleof[index].stringof.length;
        if (max < temp) max = temp;
    }
    max += 1;

    foreach (index, value; values)
    {
        writefln("%-" ~ to!string(max) ~ "s %s",
T.tupleof[index].stringof, value);
    }
}


void main()
{
    writeln();

    Foo foo = Foo(1, 2);
    printFields(foo);
}
May 07 2011
parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 07/05/2011 23:36, Andrej Mitrovic wrote:
 Not too sure, CTFE is a pain in the ass sometimes. What exactly are
 you trying to do, print field names in a custom way?

No, I have a struct that I don't have access to in the scope I'm in, I do however have its type - by using the above, I can create a local clone of the type which acts the same (at least for my purposes), which I can then do things with. Except that it fails with that error message D; -- Robert http://octarineparrot.com/
May 07 2011
parent Robert Clipsham <robert octarineparrot.com> writes:
On 08/05/2011 00:39, Andrej Mitrovic wrote:
 One simplistic solution is to use alias this to simulate the same type:

 struct Foo
 {
      int x, y;
 }

 string structClone(T)()
 {
      return "struct " ~ T.stringof ~ "_ { "
          ~ T.stringof ~ " _inner;
          alias _inner this;
          this(T...)(T t) { _inner = typeof(_inner)(t);  } };";
 }

 void main()
 {
      mixin(structClone!Foo);
      Foo_ foo = Foo_(1, 2);

      assert(foo.x == 1);
      assert(foo.y == 2);
 }

 Field initializations and ctors will work thanks to the templated ctor
 that just forwards to the _inner struct.

Unfortunately this won't do what I need - I need to be able to iterate over the members of the resulting struct using .tupleof, which I can't do with alias this. -- Robert http://octarineparrot.com/
May 07 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
One simplistic solution is to use alias this to simulate the same type:

struct Foo
{
    int x, y;
}

string structClone(T)()
{
    return "struct " ~ T.stringof ~ "_ { "
        ~ T.stringof ~ " _inner;
        alias _inner this;
        this(T...)(T t) { _inner = typeof(_inner)(t);  } };";
}

void main()
{
    mixin(structClone!Foo);
    Foo_ foo = Foo_(1, 2);

    assert(foo.x == 1);
    assert(foo.y == 2);
}

Field initializations and ctors will work thanks to the templated ctor
that just forwards to the _inner struct.
May 07 2011
prev sibling next sibling parent reply Lutger Blijdestijn <lutger.blijdestijn gmail.com> writes:
Robert Clipsham wrote:

 Hey all,
 
 I was wondering if anyone could enlighten me as to why the following
 code does not compile (dmd2, latest release or the beta):
 ----
 struct Foo
 {
      int a;
 }
 
 string test()
 {
          string str = "struct " ~ Foo.stringof ~ "_{";
          foreach (j, f; Foo.tupleof)
          {
              enum fullFieldName = Foo.tupleof[j].stringof;
              str ~= typeof(f).stringof ~ ' ' ~
 fullFieldName[Foo.stringof.length + 3 .. $];
          }
          return str ~ "}";
 }
 
 void main()
 {
      mixin(test());
 }
 ----
 If fails with the errors:
 test.d(9): Error: Cannot interpret Foo at compile time
 test.d(19): Error: cannot evaluate test() at compile time
 test.d(19): Error: argument to mixin must be a string, not (test())
 test.d(19): Error: cannot evaluate test() at compile time
 test.d(19): Error: argument to mixin must be a string, not (test())
 
 Thanks,
 

test also doesn't compile normally on my box, dmd errors on Foo.tupleof. Not sure if this is illegal or not. I think you want the allMembers trait or something similar. Something like this: import std.traits; string test(T)() { string str = "struct " ~ T.stringof ~ "_{"; alias FieldTypeTuple!T FieldTypes; foreach (i, fieldName; __traits(allMembers, T ) ) { str ~= FieldTypes[i].stringof ~ " " ~ fieldName ~ ";"; } return str ~ "}"; } This works for your example but is a bit crude, I'm sorry for that, you'll have to modify it. ( allMembers also returns functions, including ctors while FieldTypeTuple doesn't. I also haven't read anything about the order in which FieldTypeTuple and allMembers return their elements )
May 08 2011
parent Robert Clipsham <robert octarineparrot.com> writes:
On 08/05/2011 19:19, Lutger Blijdestijn wrote:
 test also doesn't compile normally on my box, dmd errors on Foo.tupleof. Not
 sure if this is illegal or not. I think you want the allMembers trait or
 something similar. Something like this:

 import std.traits;

 string test(T)()
 {
      string str = "struct " ~ T.stringof ~ "_{";
      alias FieldTypeTuple!T FieldTypes;
      foreach (i, fieldName; __traits(allMembers, T ) )
      {
          str ~= FieldTypes[i].stringof ~ " " ~ fieldName ~ ";";
      }
      return str ~ "}";
 }

 This works for your example but is a bit crude, I'm sorry for that, you'll
 have to modify it. ( allMembers also returns functions, including ctors
 while FieldTypeTuple doesn't. I also haven't read anything about the order
 in which FieldTypeTuple and allMembers return their elements )

This seems to do what I need, thanks! :D -- Robert http://octarineparrot.com/
May 08 2011
prev sibling parent reply Don <nospam nospam.com> writes:
Robert Clipsham wrote:
 Hey all,
 
 I was wondering if anyone could enlighten me as to why the following 
 code does not compile (dmd2, latest release or the beta):

Added as bug 5969.
May 09 2011
parent Robert Clipsham <robert octarineparrot.com> writes:
On 09/05/2011 16:36, Don wrote:
 Robert Clipsham wrote:
 Hey all,

 I was wondering if anyone could enlighten me as to why the following
 code does not compile (dmd2, latest release or the beta):

Added as bug 5969.

Thanks for this, I wasn't sure if it was a bug or not :) -- Robert http://octarineparrot.com/
May 09 2011