www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - const/invariant

reply Denton Cockburn <diboss hotmail.com> writes:
given a class:

class C {}

what's the difference between:

const C c = new C;
and
invariant C c = new C;

From what I can see, neither are modifiable.  So what's different 
(D2.008)?
Dec 04 2007
next sibling parent reply Derek Parnell <derek nomail.afraid.org> writes:
On Wed, 5 Dec 2007 06:46:21 +0000 (UTC), Denton Cockburn wrote:

 given a class:
 
 class C {}
 
 what's the difference between:
 
 const C c = new C;
 and
 invariant C c = new C;
 
 From what I can see, neither are modifiable.  So what's different 
 (D2.008)?

Dunno, except that you have to say ... const C c = new C; invariant C d = cast(invariant Foo)new C; And what I don't get is why would anyone bother with const/invariant for classes since you can't invoke any member functions when you do. -------------- class Foo { int mbr; this() { mbr = 6174; } int get() {return mbr; } } void main() { const Foo c = new Foo(); int a; a = c.get(); } -------------- I get the error messages ... : function test.Foo.get () does not match parameter types () : Error: c.get can only be called on a mutable object, not const(Foo) Aside from the useless message text "function test.Foo.get () does not match parameter types ()" that doesn't actually tell me the problem is, I can't see why this is forbidden. I can see that get() doesn't change anything but the compiler still will not let me call it. So if one can't call any member function in the const object, what is the point of it? Sure I can cast the const away but why would I want to do that for every invocation of a member function? I really don't get the point of const objects when implemented this way. I thought it might be a way to tell the compiler that I can't call member functions that happen to change member values. That would make sense to me. -- Derek (skype: derek.j.parnell) Melbourne, Australia 5/12/2007 6:20:05 PM
Dec 04 2007
parent Derek Parnell <derek psych.ward> writes:
On Wed, 5 Dec 2007 07:43:14 +0000 (UTC), Denton Cockburn wrote:

 declare get() const and it'll work.
 
 const int get { return mbr; }

Duh! </me slaps forehead> Ummm, yeah that makes sense. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Dec 05 2007
prev sibling next sibling parent Denton Cockburn <diboss hotmail.com> writes:
On Wed, 05 Dec 2007 18:30:37 +1100, Derek Parnell wrote:

 On Wed, 5 Dec 2007 06:46:21 +0000 (UTC), Denton Cockburn wrote:
 
 given a class:
 
 class C {}
 
 what's the difference between:
 
 const C c = new C;
 and
 invariant C c = new C;
 
 From what I can see, neither are modifiable.  So what's different
 (D2.008)?

Dunno, except that you have to say ... const C c = new C; invariant C d = cast(invariant Foo)new C; And what I don't get is why would anyone bother with const/invariant for classes since you can't invoke any member functions when you do. -------------- class Foo { int mbr; this() { mbr = 6174; } int get() {return mbr; } } void main() { const Foo c = new Foo(); int a; a = c.get(); } -------------- I get the error messages ... : function test.Foo.get () does not match parameter types () : Error: c.get can only be called on a mutable object, not const(Foo) Aside from the useless message text "function test.Foo.get () does not match parameter types ()" that doesn't actually tell me the problem is, I can't see why this is forbidden. I can see that get() doesn't change anything but the compiler still will not let me call it. So if one can't call any member function in the const object, what is the point of it? Sure I can cast the const away but why would I want to do that for every invocation of a member function? I really don't get the point of const objects when implemented this way. I thought it might be a way to tell the compiler that I can't call member functions that happen to change member values. That would make sense to me.

You can call const member functions. Since the 2.008 changes, I'm missing the use of invariant for things that are passed by ref, like arrays and objects.
Dec 04 2007
prev sibling next sibling parent Denton Cockburn <diboss hotmail.com> writes:
declare get() const and it'll work.

const int get { return mbr; }
Dec 04 2007
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Denton Cockburn" wrote
 given a class:

 class C {}

 what's the difference between:

 const C c = new C;
 and
 invariant C c = new C;

 From what I can see, neither are modifiable.  So what's different
 (D2.008).

const class references can be used to call const member functions, but cannot call normal member functions or invariant member functions. invariant class references can be used to call const or invariant member functions, but not normal member functions. normal class references can call normal member functions and const member functions, but not invariant member functions. In your example, there is no other non-const reference of c, so technically, it is invariant because nothing outside of the c reference can ever change it. Therefore, the second declaration is more accurate and gives you more ability (you can now call invariant functions). if you had something like: C c = new C; const C c2 = c; invariant C c3 = cast(invariant)c; // this is bad Now, c2 cannot be declared invariant because something using the c reference could modify the data. c2 is like a read only view of c, it can look but cannot touch. c3 is bad because before you cast to invariant, you must ensure that no other references to the same data can modify the class. Anticipating your next question: what is the difference between invariant and const functions? Code-wise, nothing. However, the compiler is free to make better optimizations knowing that none of the members of the class will change. -Steve
Dec 05 2007
parent Derek Parnell <derek nomail.afraid.org> writes:
On Wed, 5 Dec 2007 10:00:28 -0500, Steven Schveighoffer wrote:

 "Denton Cockburn" wrote
 given a class:

 class C {}

 what's the difference between:

 const C c = new C;
 and
 invariant C c = new C;

 From what I can see, neither are modifiable.  So what's different
 (D2.008).

const class references can be used to call const member functions, but cannot call normal member functions or invariant member functions. invariant class references can be used to call const or invariant member functions, but not normal member functions. normal class references can call normal member functions and const member functions, but not invariant member functions.

Thanks Steve, I guess this should be made clearer in the documentation. Maybe a table such as ... "Can Call" Table: Member Function Instance Declaration+----------------------------+ -------------------| normal | const | invariant | ----------+--------+-------+-----------+ normal | Y | Y | N | ----------+--------+-------+-----------+ const | N | Y | N | ----------+--------+-------+-----------+ invariant| N | Y | Y | ----------+--------+-------+-----------+ -- Derek (skype: derek.j.parnell) Melbourne, Australia 6/12/2007 9:41:44 AM
Dec 05 2007
prev sibling parent guslay <guslay gmail.com> writes:
 
 class C {}
 
 what's the difference between:
 
 const C c = new C;
 and
 invariant C c = new C;
 

I don't see any difference between const and invariant when they are constructed locally, like in your example. The compiler know they can't change. There is a difference however when they are passed as argument to a function. void foo( const/invariant int* x ) {...} In the const case, the value refered by x can be modified between the beginning and the end of the function. Not directly, but indirectly, either by aliasing (see http://www.digitalmars.com/d/const3.html) or in maybe if x is shared between threads. Invariant are guaranteed to never change, directly or indirectly. It's my understanding. I hope i'm not spreading too much wrongness.
Dec 05 2007