Thread overview
Initialization of const struct
Jan 08, 2006
Garett Bass
Jan 09, 2006
James Dunne
Jan 09, 2006
Chris Sauls
Jan 09, 2006
James Dunne
Jan 10, 2006
Garett Bass
January 08, 2006
I'm trying to store some const data in a struct nested within a class.  I want to initialize the struct during the class constructor, and let the compiler prevent me from subsequently changing the const data.  I tried two different approaches, Foo and Bar in the code listing below.

In class Foo, Internal.i is declared const, but I am able to change its value without any complaint from the compiler.  Is this a bug or a feature?

In class Bar, internal is declared const, but I don't know what syntax I should use to initialize it.  Also, I'm not certain that the declaration "const Internal internal" would prevent me from subsequently changing Internal.i even if I could initialize it.

Thanks in advance to anyone who can correct my understanding of this.

Regards,
Garett

------------
module test;
private import std.stdio;

class Foo {
   struct Internal {
       const int i;
   }
      Internal internal;

   this() {
       internal.i = 0; // OK
       internal.i = 2; // Why is this ok?
   }
}

/* // Error: constructor missing initializer for const field internal
class Bar {
   struct Internal {
       int i;
   }
      const Internal internal;

   this() {
       //internal = { i:2; }; // Error: expression expected, not '{'
   }
}
*/

int main(char[][] args) {
   auto Foo foo = new Foo;
   //auto Bar bar = new Bar;
      return 0;
}
January 09, 2006
Garett Bass wrote:
> I'm trying to store some const data in a struct nested within a class.  I want to initialize the struct during the class constructor, and let the compiler prevent me from subsequently changing the const data.  I tried two different approaches, Foo and Bar in the code listing below.
> 
> In class Foo, Internal.i is declared const, but I am able to change its value without any complaint from the compiler.  Is this a bug or a feature?
> 
> In class Bar, internal is declared const, but I don't know what syntax I should use to initialize it.  Also, I'm not certain that the declaration "const Internal internal" would prevent me from subsequently changing Internal.i even if I could initialize it.
> 
> Thanks in advance to anyone who can correct my understanding of this.
> 
> Regards,
> Garett
> 
> ------------
> module test;
> private import std.stdio;
> 
> class Foo {
>    struct Internal {
>        const int i;
>    }
>       Internal internal;
> 
>    this() {
>        internal.i = 0; // OK
>        internal.i = 2; // Why is this ok?
>    }
> }

A few problems here:

1) *...goes to look up rules concerning const members of structs...* Well, the D language spec says nothing (to my eyes) about const members of structs.  Perhaps it is mentioned somewhere else in the spec as a blanket statement concerning all const members of aggregate types that I may have missed in my quick check.

2) I'm assuming that if this compiles correctly in the first place, then there is definitely a bug in DMD concerning const members of structs, since you didn't specify any initializer for your Internal.i in the struct definition.  Here is some 'more correct' code that you may be looking for:

> class Foo {
>    struct Internal {
>        const int i = 0;
>    }
>    Internal internal;
>
>    this() {
>    }
> }

No initialization of internal.i is needed in the constructor, since 'i' should be const.  But why do you have a struct which only contains a const member?  Obviously there's more to your problem than meets the eye in your original post.

> 
> /* // Error: constructor missing initializer for const field internal
> class Bar {
>    struct Internal {
>        int i;
>    }
>       const Internal internal;
> 
>    this() {
>        //internal = { i:2; }; // Error: expression expected, not '{'
>    }
> }
> */
> 
> int main(char[][] args) {
>    auto Foo foo = new Foo;
>    //auto Bar bar = new Bar;
>       return 0;
> }

Now a const struct doesn't make a whole lot of sense here.  You cannot initialize const members in a constructor.  Const is a compile-time construct, where you must explicitly tell the *compiler* what it is the constant could be; this is only possibly (currently) through the use of initializer expressions on the const declaration.

What you might be looking for is the following:

> class Bar {
>    struct Internal {
>        int i;
>    }
>       const Internal internal = { i:2; };
>
>    this() {
>    }
> }

Hope this helps.  If not, maybe provide a little more insight into your problem.
January 09, 2006
James Dunne wrote:
> Now a const struct doesn't make a whole lot of sense here.  You cannot initialize const members in a constructor.  Const is a compile-time construct, where you must explicitly tell the *compiler* what it is the constant could be; this is only possibly (currently) through the use of initializer expressions on the const declaration.

Not true.  Quoted directly from (http://digitalmars.com/d/attribute.html#const) :
  """A const declaration without an initializer must be initialized in a constructor (for class fields) or in a static constructor (for static class members, or module variable declarations)."""

I've used this feature a few times.

-- Chris Sauls
January 09, 2006
Chris Sauls wrote:
> James Dunne wrote:
> 
>> Now a const struct doesn't make a whole lot of sense here.  You cannot initialize const members in a constructor.  Const is a compile-time construct, where you must explicitly tell the *compiler* what it is the constant could be; this is only possibly (currently) through the use of initializer expressions on the const declaration.
> 
> 
> Not true.  Quoted directly from (http://digitalmars.com/d/attribute.html#const) :
>   """A const declaration without an initializer must be initialized in a constructor (for class fields) or in a static constructor (for static class members, or module variable declarations)."""
> 
> I've used this feature a few times.
> 
> -- Chris Sauls

I see.  Then is there nothing that states that your const variable cannot be changed within the constructor after its first assignment? This part doesn't make much sense if a second assignment as disallowed.  What if you have to perform some sort of recursive calculation on your const variable?

Then, in the OP the code is correct.  You just cannot change the value of 'i' in any other method besides the constructor.
January 10, 2006
James Dunne wrote:
> Then, in the OP the code is correct.  You just cannot change the value of 'i' in any other method besides the constructor.

Yet, sadly, you can change "const" internal.i anytime you please...

------------
module test;
private import std.stdio;

class Foo {
   struct Internal {
       const int i;
   }
   Internal internal;

   this() {
       internal.i = 0; // OK
       internal.i = 2; // Why is this ok?
   }

   int i()      { return internal.i; }
   int i(int i) { return internal.i = i; } // NOT CONST!
}

int main(char[][] args) {
   auto Foo foo = new Foo;

   writefln("foo.i = %d", foo.i = 4);

   return 0;
}