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