www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Initialization of const struct

reply Garett Bass <garettbass studiotekne.com> writes:
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;
}
Jan 08 2006
parent reply James Dunne <james.jdunne gmail.com> writes:
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.
Jan 09 2006
parent reply Chris Sauls <ibisbasenji gmail.com> writes:
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
Jan 09 2006
parent reply James Dunne <james.jdunne gmail.com> writes:
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.
Jan 09 2006
parent Garett Bass <garettbass studiotekne.com> writes:
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; }
Jan 09 2006