Clarifying 'const' terminology
Bruno Medeiros
brunodomedeirosATgmail at SPAM.com
Sun Jul 9 03:12:00 PDT 2006
Sean Kelly wrote:
> Bruno Medeiros wrote:
>> Derek Parnell wrote:
>>> I'm not from a C++/C#/Java background, so please excuse my lack of
>>> understanding about the meaning that is being applied to the term
>>> 'const' in these recent discussions.
>>>
>>
>> I think many times people talked a bit vaguely with their meaning of
>> const.
>>
>>> To me, there seems to be two things being talked about.
>>>
>>> (a) Data, which once initialized, is not to be modified for the
>>> run-time life of the application.
>>>
>>> (b) Data, which once passed to some function, is not to be modified
>>> for the run-time life of that function.
>>>
>>> Walter's proposed refinement of the 'in' keyword does nothing for
>>> type (a), and only limited support for type (b), in that it protects
>>> data from the called function but not from functions that that
>>> subsequently calls. It is only protection for one level deep. And the
>>> only data protected is class objects and not other reference types.
>>>
>>> Is there any other types (or subtypes) of 'const' meanings being
>>> discussed or considered?
>>>
>>> For example, are we distinguishing between compile-time protection
>>> and run-time protection?
>>>
>>
>> 'const', in a general sense, is a mechanism to specify whether a
>> variable/data/object can or can not modified, and enforce that
>> contract (at compile time). 'const' is usually in the sense of (b),
>> that is, some parts of code may modify the data, while others can only
>> read it (thus it is used for ownership management). That's the case
>> for C++.
>> Enforcing the contract means you cannot assign a const variable to a
>> non-const one, or similarly, pass a const variable to a function that
>> expects a non-const argument. The only way to subvert this is with a
>> cast (which should be the only way to subvert anything).
>
> In the realm of compiler optimization techniques, there's another issue
> as well: can the compiler assume that, because it is evaluating a const
> reference, that the underlying data will not change while that reference
> is in use. This is the truly sticky part, and is I think a large reason
> why Walter hasn't settled on anything yet. For example, consider "const
> by default":
>
> void readWrite( inout T val ) {}
> void readOnly( in T val ) {}
>
> T val;
>
> readWrite( inout val );
> ...
> readOnly( val );
>
> In the above, because a mutable reference to val is obtained before
> readOnly is called, can the compiler assume that the contents of val
> will not change while readOnly is being evaluated? Can it ever make
> that assumption for the entire life of the program after readWrite is
> called?
>
Yes, but one has to realize that that is a different thing from the
readonly view type of immutability, which is used for ownership
management. You can't have 'const' or any other keyword mean both things.
C++'s 'const' has only the meaning of a readonly view type of contract.
It does not mean the data cannot change (although in case of a value
type, it indeed can't). I recall the discussion between Walter and
Alexei where Walter complained that C++'s const was not very useful
because it didn't guarantee data was non-changing. Alexei took a while
to make Walter understand that that was not the purpose and usefulness
of the kind of const/language-construct that he was considering
important (which was the readonly view construct).
>> There are some variations in const semantics. In C++, const is a
>> type-modifier, meaning that const can be applied to each type element,
>> and not the "variable as whole". Best to give an example. In C++ you
>> can have:
>> const int * iptr = ...;
>> int const * iptr = ...;
>
> These two are actually identical. Though things can get a bit tricky if
> 'int' is replaced by a typedef involving a reference type, which is why
> the latter form tends to be preferred these days--it is unambiguous,
> unlike the former form.
>
>> const int const * iptr = ...;
>> each with different meanings:
>
> I believe this is the same as the above, you merely applied the const to
> int twice. What you probably meant for these three was:
>
> const int * iptr = ...; // mutable ptr to const int
> int const * iptr = ...; // same as previous line
> int * const iptr = ...; // const ptr to mutable int
> const int * const iptr = ...; // const ptr to const int
> int const * const iptr = ...; // same as previous line
>
Yes, Deewiant had pointed that out already. ;)
> To return to the typedef issue for a moment, if you do:
>
> typedef char* pchar;
>
> template<class T> void func( const T val ) {}
>
> pchar val = "hello";
>
> func( val );
>
> then it's not entirely clear whether the val in func is a const pointer
> to mutable data or vice-versa. Thus the preferred method is:
>
> template<class T> void func( T const val ) {}
>
> Where it's obvious that the 'const' will apply to the pointer if one
> exists.
>
>
> Sean
Another of C++'s subtle trickinesses... I'll keep that in mind, if I
have to deal with it in the future.
--
Bruno Medeiros - CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
More information about the Digitalmars-d-learn
mailing list