What's the authoritative difference between immutable and const for reference types?

Michel Fortin michel.fortin at michelf.com
Sat Jun 26 05:48:35 PDT 2010


On 2010-06-26 08:12:24 -0400, Justin Johansson <no at spam.com> said:

> Simen kjaeraas wrote:
>> Justin Johansson <no at spam.com> wrote:
>> 
>>> Specifically, I wish to have class which has a member variable which 
>>> cannot be changed (and is guaranteed not to change) and this member 
>>> variable happens to be a reference type (i.e. it's a pointer in C++ 
>>> parlance) and, further more, the instance of the class which that 
>>> variable refers to is to be deep immutable.
>>> 
>>> For instance, with
>>> 
>>> class Foo
>>> {
>>> }
>>> 
>>> class Bar
>>> {
>>>     Foo foo;
>>> }
>>> 
>>> consider instances of Foo to be in ROM and instances of Bar to be in 
>>> RAM   and once a Bar instance is constructed, the member variable foo 
>>> itself is not allowed to be modified.
>> 
>> What you want is
>> 
>> class Bar
>> {
>>     immutable Foo foo;
>> }
>> 
>> Now, I believe there are some problems constructing immutable objects, for
>> which the assumeUnique template in std.contracts is created.
>> 
> 
> Thanks for that Simen.
> 
> Thinking about this a bit more, there are four possibilities as 
> indicated in the following table :-
> 
>    Variable foo is modifiable | Data referred to by foo is modifiable
>    ---------------------------+--------------------------------------
>           No                  |          No
>           No                  |          Yes
>           Yes                 |          No
>           Yes                 |          Yes
>    ---------------------------+--------------------------------------
> 
> What combination of immutable and const storage classes make for the 
> implementation of these four possibilities?

I think your table isn't very practical because it eludes the question 
of "modifiable by whom?". If you have a const(int)*, the integer it 
points to cannot be modified *through this pointer*, but you could have 
another a non-const pointer lying elsewhere through which you can 
change the integer. If you had a immutable(int)*, then you know that no 
where in the program lies a non-const reference to it and as such you 
know the value of the integer will never change. So const means you 
can't modify it; immutable means nobody can modify it and the value is 
guarantied to stay constant.

As for your table, the answer is this:

	1. const(int*) foo;    or    immutable(int*) foo;
	2. // impossible in D, constness is transitive propagates to referenced data
	3. const(int)* foo;    or    immutable(int)* foo;
	4. int* foo;

Notice that both const and immutable can be used interchangeably to 
fill your table as it depends on something you left unspecified: 
whether the data is unmodifiable through this pointer only or truly 
unmodifiable from everywhere in the program. That's the essence of the 
difference between const and immutable.

Now, when it comes to classes and objects you have the problem that 
they're implicitly references and because of this you can't use a 
different constness for the object and the reference to it. That's a 
syntactic problem because there are no '*' marker to include or 
exclude. The only solution for now is to use a struct that casts its 
way around the problem. See Rebindable in std.typecons (but in my 
experience it doesn't work very well).


-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



More information about the Digitalmars-d mailing list