www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Initializing const member post-construction?

reply Jerry Quinn <jlquinn optonline.net> writes:
Hi.  I'm trying to port a C++ program to D as an exercise in exploring D.  As
I'm doing this, I've run into a bit of confusion with the const system.

I have something like

class A {}
class B {
  const A a;
  void init(A aa) { a = aa; }
}

This doesn't work, because dmd (2.020) complains that you can't initialize a
const member after the constructor.  The catch is that the value of aa is not
available at construction time, but only later on.  However, I'd still like to
declare that once set, the object referred to by a is const.

The C++ code used a pointer, but it seemed to me like D's references were more
capable than C++'s, so I'm trying to use them.

To me it seems like this should still be allowed.  Even though the object
referred to by a is const, the reference itself shouldn't need to be.  This
seems morally equivalent to:

const(A)* a;

which is allowed by dmd.  In both cases I'm trying to tell the compiler that
the object referred to by a is const.

Is there a way to do what I'm trying to do?  What's the reason for not allowing
this?

Thanks,
Jerry
Oct 27 2008
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Jerry Quinn" wrote
 Hi.  I'm trying to port a C++ program to D as an exercise in exploring D. 
 As I'm doing this, I've run into a bit of confusion with the const system.

 I have something like

 class A {}
 class B {
  const A a;
  void init(A aa) { a = aa; }
 }

 This doesn't work, because dmd (2.020) complains that you can't initialize 
 a const member after the constructor.  The catch is that the value of aa 
 is not available at construction time, but only later on.  However, I'd 
 still like to declare that once set, the object referred to by a is const.

 The C++ code used a pointer, but it seemed to me like D's references were 
 more capable than C++'s, so I'm trying to use them.

 To me it seems like this should still be allowed.  Even though the object 
 referred to by a is const, the reference itself shouldn't need to be. 
 This seems morally equivalent to:

 const(A)* a;

 which is allowed by dmd.  In both cases I'm trying to tell the compiler 
 that the object referred to by a is const.

 Is there a way to do what I'm trying to do?

You can hide a behind a property: class B { private A aPriv; void init(A aa) { aPriv = aa; } const(A) a() const { return aPriv;} } Now, do not use aPriv anywhere else in your code, and you should be all set. Use -inline when compiling and you should see no performance penalty.
 What's the reason for not allowing this?

I was unaware you could even set a in the constructor. I don't think there's any general 'set once' type modifier. -Steve
Oct 28 2008
next sibling parent reply Lars Kyllingstad <public kyllingen.NOSPAMnet> writes:
Steven Schveighoffer wrote:
 "Jerry Quinn" wrote
 Hi.  I'm trying to port a C++ program to D as an exercise in exploring D. 
 As I'm doing this, I've run into a bit of confusion with the const system.

 I have something like

 class A {}
 class B {
  const A a;
  void init(A aa) { a = aa; }
 }

 This doesn't work, because dmd (2.020) complains that you can't initialize 
 a const member after the constructor.  The catch is that the value of aa 
 is not available at construction time, but only later on.  However, I'd 
 still like to declare that once set, the object referred to by a is const.

 The C++ code used a pointer, but it seemed to me like D's references were 
 more capable than C++'s, so I'm trying to use them.

 To me it seems like this should still be allowed.  Even though the object 
 referred to by a is const, the reference itself shouldn't need to be. 
 This seems morally equivalent to:

 const(A)* a;

 which is allowed by dmd.  In both cases I'm trying to tell the compiler 
 that the object referred to by a is const.

 Is there a way to do what I'm trying to do?

You can hide a behind a property: class B { private A aPriv; void init(A aa) { aPriv = aa; } const(A) a() const { return aPriv;} } Now, do not use aPriv anywhere else in your code, and you should be all set. Use -inline when compiling and you should see no performance penalty.
 What's the reason for not allowing this?

I was unaware you could even set a in the constructor. I don't think there's any general 'set once' type modifier. -Steve

Isn't that what 'final' is for? I can't seem to find any details on it in the D1 specs, but at least that's what it does in Java. I'm not sure it's implemented in D1 (yet?), though. BTW, if you don't initialise a const member variable upon declaration, then it *must* be initialised in every constructor, I think. -Lars
Oct 28 2008
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Lars Kyllingstad" wrote
 Steven Schveighoffer wrote:
 "Jerry Quinn" wrote
 Hi.  I'm trying to port a C++ program to D as an exercise in exploring 
 D. As I'm doing this, I've run into a bit of confusion with the const 
 system.

 I have something like

 class A {}
 class B {
  const A a;
  void init(A aa) { a = aa; }
 }

 This doesn't work, because dmd (2.020) complains that you can't 
 initialize a const member after the constructor.  The catch is that the 
 value of aa is not available at construction time, but only later on. 
 However, I'd still like to declare that once set, the object referred to 
 by a is const.

 The C++ code used a pointer, but it seemed to me like D's references 
 were more capable than C++'s, so I'm trying to use them.

 To me it seems like this should still be allowed.  Even though the 
 object referred to by a is const, the reference itself shouldn't need to 
 be. This seems morally equivalent to:

 const(A)* a;

 which is allowed by dmd.  In both cases I'm trying to tell the compiler 
 that the object referred to by a is const.

 Is there a way to do what I'm trying to do?

You can hide a behind a property: class B { private A aPriv; void init(A aa) { aPriv = aa; } const(A) a() const { return aPriv;} } Now, do not use aPriv anywhere else in your code, and you should be all set. Use -inline when compiling and you should see no performance penalty.
 What's the reason for not allowing this?

I was unaware you could even set a in the constructor. I don't think there's any general 'set once' type modifier. -Steve

Isn't that what 'final' is for? I can't seem to find any details on it in the D1 specs, but at least that's what it does in Java. I'm not sure it's implemented in D1 (yet?), though.

Yes, I believe that is what final is for in D1. But the OP is using D2, and I believe that context for final was removed (it is now only used on member functions to mean that the function is no longer virtual). -Steve
Oct 28 2008
prev sibling parent reply Jerry Quinn <jlquinn optonline.net> writes:
Steven Schveighoffer Wrote:

 "Jerry Quinn" wrote
 Hi.  I'm trying to port a C++ program to D as an exercise in exploring D. 
 As I'm doing this, I've run into a bit of confusion with the const system.

 I have something like

 class A {}
 class B {
  const A a;
  void init(A aa) { a = aa; }
 }

 This doesn't work, because dmd (2.020) complains that you can't initialize 
 a const member after the constructor.  The catch is that the value of aa 
 is not available at construction time, but only later on.  However, I'd 
 still like to declare that once set, the object referred to by a is const.

 The C++ code used a pointer, but it seemed to me like D's references were 
 more capable than C++'s, so I'm trying to use them.

 To me it seems like this should still be allowed.  Even though the object 
 referred to by a is const, the reference itself shouldn't need to be. 
 This seems morally equivalent to:

 const(A)* a;

 which is allowed by dmd.  In both cases I'm trying to tell the compiler 
 that the object referred to by a is const.

 Is there a way to do what I'm trying to do?

You can hide a behind a property: class B { private A aPriv; void init(A aa) { aPriv = aa; } const(A) a() const { return aPriv;} } Now, do not use aPriv anywhere else in your code, and you should be all set. Use -inline when compiling and you should see no performance penalty.

Yes, that seems to be a reasonable workaround. Thanks.
 What's the reason for not allowing this?

I was unaware you could even set a in the constructor. I don't think there's any general 'set once' type modifier.

No, I didn't see one either. In fact what I was asking for is not a set once. It's to allow a reference to a const object to be reassigned, since it wasn't obvious to me that the reference itself should be kept const. Jerry
Oct 28 2008
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Jerry Quinn" wrote
 Steven Schveighoffer Wrote:
 I was unaware you could even set a in the constructor.  I don't think
 there's any general 'set once' type modifier.

No, I didn't see one either. In fact what I was asking for is not a set once. It's to allow a reference to a const object to be reassigned, since it wasn't obvious to me that the reference itself should be kept const.

Oh, for this there is std.typecons.Rebindable: Rebindable!(const(A)) a; Not sure how close it is to the real thing, I haven't used it. -Steve
Oct 28 2008