Thread overview
const/invariant
Dec 05, 2007
Denton Cockburn
Dec 05, 2007
Derek Parnell
Dec 05, 2007
Denton Cockburn
Dec 05, 2007
Denton Cockburn
Dec 05, 2007
Derek Parnell
Dec 05, 2007
Derek Parnell
Dec 05, 2007
guslay
December 05, 2007
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)?
December 05, 2007
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
December 05, 2007
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.
December 05, 2007
declare get() const and it'll work.

const int get { return mbr; }

December 05, 2007
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
December 05, 2007
"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


December 05, 2007
> 
> 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.

December 05, 2007
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