What's the authoritative difference between immutable and const for reference types?
Justin Johansson
no at spam.com
Sat Jun 26 12:05:39 PDT 2010
Michel Fortin wrote:
> 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).
>
Thanks for the detailed explanation, especially that you have addressed
all 4 possibilities (even though, as you say, the table might be
impractical) and also identified the syntactic problem when it comes to
classes and objects.
More information about the Digitalmars-d
mailing list