Immutable struct fields

Dmitry Olshansky dmitry.olsh at gmail.com
Mon Nov 1 14:52:54 PDT 2010


On 02.11.2010 0:24, bearophile wrote:
> To answer the recent D.learn thread "How would I optimize this parser?", I have tried to find a more efficient way to build the parse tree, so I have used tagged structs, something like this:
>
>
> enum NodeType { node, text, tag }
>
> struct Node {
>      /*immutable*/ NodeType type = NodeType.node;
>      Node* parent;
> }
>
> struct TextNode {
>      /*immutable*/ NodeType type = NodeType.text;
>      Node* parent;
>      string content;
>
>      public nothrow this(string content) {
>          this.content = content;
>      }
> }
>
> struct TagNode {
>      /*immutable*/ NodeType type = NodeType.tag;
>      Node* parent;
>      string name;
>      Node*[] children;
>
>      public nothrow this(string name) {
>          this.name = name;
>      }
>
>      public nothrow void addChild(Node* newChild) {
>          children ~= newChild;
>          newChild.parent = cast(Node*)&this;
>      }
> }
>
>
> Each struct instance contains a "type" tag that at runtime tells what kind of node it is. This tag never changes in the life of a node, so it's better for it to be immutable, to use the type system to avoid changing it by mistake.
>
> But unfortunately it doesn't work, this is a reduced example:
>
>
> struct Foo {
>      immutable int x = 1;
> }
> struct Bar {
>      immutable int x = 2;
> }
> static assert(Foo.sizeof == 4);
> void main() {
>      Foo f;
>      assert(f.x == 1);
>      assert((cast(Bar)f).x == 1);
> }
>
>
> It seems that immutable fields act like static const fields or enum fields, they have no storage. This seems a little weird to me. Do you know a way to put immutable storage in a struct instance?
>
> Using this doesn't work:
>
> this(int) { type = NodeType.tag; }
>
> And a static this() doesn't seem to work. So in the program I have just used a mutable type field, but it looks silly...
>
> Bye,
> bearophile
Wierd indeed, best workaround I can come up with:
struct Foo {
     immutable int x;
     private this(int val){ x = val; }
     public  static Foo opCall(){
          return Foo(1);
     }
}
struct Bar {
     immutable int x;
     private this(int val){ x = val; }
     public  static Bar opCall(){
          return Bar(2);
     }

}
static assert(Foo.sizeof == 4);
void main() {
     Foo f = Foo();
     assert(f.x == 1);
     assert((cast(Bar*)&f).x == 1);
}

works, and the fact that static opCall is deprecated(?) makes me wish 
it's a compiler bug.
And you still could shoot yourself in the leg, but only explicitly (that 
is "Foo f = Foo(42)" ) and only in the same module.

-- 
Dmitry Olshansky



More information about the Digitalmars-d-learn mailing list