Topic: const' revisited


Author: twagner@baobab.berkeley.edu (Tim Wagner)
Date: 27 Aug 90 00:33:10 GMT
Raw View
Unfortunately, what does one do when per-instance information is
required?  The following cannot possibly be acceptable to anyone:

#pragma this-means-really-const
const i;
#pragma this-means-interface-const
const j;
...

'pragma' as a replacement for language-integrated type information
would be the supreme sacrifice in this case.




Author: pcg@cs.aber.ac.uk (Piercarlo Grandi)
Date: 17 Aug 90 16:07:37 GMT
Raw View
On 15 Aug 90 21:28:31 GMT, DEREK@AppleLink.apple.com (Derek White) said:

DEREK> In fact, the recent examples that have shown a need for
DEREK> "partially const" objects have fallen in the same catagory: I
DEREK> think they can be solved by seperating the constant and variable
DEREK> portions of an object into constant and varying fields or
DEREK> classes.

Excellent point. Moreover 'const' in C++ already has the right
definition; thank Stroustrup for not having botched it like in Ansi C. i
would hate that any debate on 'const' opened the way for the usual call
to greater Ansi C conformity. Fortunately C++ is quite a different
language.

DEREK> Although it may be expedient to make a statement that an object
DEREK> is const when it really isn't, I think in the long run honesty is
DEREK> the best policy.  I suggest a hard line approach: const is
DEREK> constant.

Again, we go back to my usual and tired observation; what we wnat to
achieve is reuse of interface, proof and implementation, and overloading
keywords can only go so far to this end (see how strained is the syntax
for the = 0 virtual function case). C++ should provide mechanisms
towards this, and mostly implementation oriented. 'const' as such is a
statement on the implementation of an object, not on its interface or
semantics.

--
Piercarlo "Peter" Grandi           | ARPA: pcg%uk.ac.aber.cs@nsfnet-relay.ac.uk
Dept of CS, UCW Aberystwyth        | UUCP: ...!mcsun!ukc!aber-cs!pcg
Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk




Author: chased@rbbb.Eng.Sun.COM (David Chase)
Date: 17 Aug 90 19:22:11 GMT
Raw View
Speaking not as a C++ expert (because I'm not) but as someone who
might care about what an optimizing compiler could infer from "const",
I think that #pragma's should be used to give the compiler hints to
enable optimization, and that "const" (and its ilk) should be used in
whatever sense is most helpful to programmers and program maintainers.

The reasoning goes like this -- (1) there's LOTS of things that a
compiler might want to know about the behavior of a subroutine, (2)
and it isn't clear that "const" is the most important of them, (3)
adding keywords or abusing combinations of existing keywords to get
the additional information is likely to result in confusing cruft
irrelevant to the correctness of the program (much like "register" in
the old days).  The choice of what is best to know about a program
could well vary from processor to processor or from compiler to
compiler, so it isn't clear that this should be standardized just yet.
Thus, don't make it part of a language that is being standardized.

For example, a procedure passed a pointer might modify it or not,
or might store it in a global variable for later modification or
examination.  Pass the address of a local to a procedure that stores
it in a global, and you can't eliminate tail-calls.  Even if a
procedure does assign through a pointer, it's good to know when it
doesn't store the pointer someplace where OTHER procedures can assign
through it.

It's also slightly useful, on a multiprocessor, to know if a
subroutine called from within a loop modifies global data.  It's much
easier to run the loop body in parallel if any subroutines called
within the loop don't modify globally visible (shared) data.

David Chase
Sun Microsystems




Author: cimshop!davidm@uunet.UU.NET (David S. Masterson)
Date: 20 Aug 90 07:21:53 GMT
Raw View
In article <140877@sun.Eng.Sun.COM> chased@rbbb.Eng.Sun.COM (David Chase)
writes:

   Speaking not as a C++ expert (because I'm not) but as someone who
   might care about what an optimizing compiler could infer from "const",
   I think that #pragma's should be used to give the compiler hints to
   enable optimization, and that "const" (and its ilk) should be used in
   whatever sense is most helpful to programmers and program maintainers.

I agree with this sentiment, but think the thrust should be reversed (in
general).  That is, I think #pragma's should be used to give the compiler
hints that standard optimization will not work with the current program.  The
language itself (since it derives from C) should promote optimization in its
structure, not as a by-product of implementation specifics (as in the
#pragma's).
--
====================================================================
David Masterson     Consilium, Inc.
uunet!cimshop!davidm    Mtn. View, CA  94043
====================================================================
"If someone thinks they know what I said, then I didn't say it!"




Author: cimshop!davidm@uunet.UU.NET (David S. Masterson)
Date: 20 Aug 90 07:31:20 GMT
Raw View
In article <PCG.90Aug17170737@athene.cs.aber.ac.uk> pcg@cs.aber.ac.uk
(Piercarlo Grandi) writes:

   Again, we go back to my usual and tired observation; what we wnat to
   achieve is reuse of interface, proof and implementation, and overloading
   keywords can only go so far to this end (see how strained is the syntax
   for the = 0 virtual function case). C++ should provide mechanisms
   towards this, and mostly implementation oriented. 'const' as such is a
   statement on the implementation of an object, not on its interface or
   semantics.

I agree that overloading keywords "can only go so far", but the interface of
an object is *part* of the implementation of the object.  I see no reason why
'const' is not also a statement of the interface to an object (as in constant,
public pointer to private data areas).  Thus far, I have not seen anything
that needs a partial const that couldn't be solved by using a constant, public
interface to a private data item.
--
====================================================================
David Masterson     Consilium, Inc.
uunet!cimshop!davidm    Mtn. View, CA  94043
====================================================================
"If someone thinks they know what I said, then I didn't say it!"




Author: jimad@microsoft.UUCP (Jim ADCOCK)
Date: 20 Aug 90 18:38:37 GMT
Raw View
In article <CIMSHOP!DAVIDM.90Aug20002153@uunet.UU.NET> cimshop!davidm@uunet.UU.NET (David S. Masterson) writes:
>
>I agree with this sentiment, but think the thrust should be reversed (in
>general).  That is, I think #pragma's should be used to give the compiler
>hints that standard optimization will not work with the current program.  The
>language itself (since it derives from C) should promote optimization in its
>structure, not as a by-product of implementation specifics (as in the
>#pragma's).

I think this is a pretty good solution.  Its only disadvantage is that the
#pramga's need to be in the .h files, further eroding the distinct
between specification and implementation.  But, if you don't do it,
you don't see the ugliness in your .h files....

This ties in well with the C++ philosophy that people who don't need a
feature shouldn't be the ones to pay for it -- people who don't cast
away from const shouldn't pay a price for those who do cast-away consts.
I like this a lot better than Koenig's suggestion where everybody has
to pay the price for cast-aways!




Author: jimad@microsoft.UUCP (Jim ADCOCK)
Date: 20 Aug 90 16:32:52 GMT
Raw View
In article <140877@sun.Eng.Sun.COM| chased@rbbb.Eng.Sun.COM (David Chase) writes:
|Speaking not as a C++ expert (because I'm not) but as someone who
|might care about what an optimizing compiler could infer from "const",
|I think that #pragma's should be used to give the compiler hints to
|enable optimization, and that "const" (and its ilk) should be used in
|whatever sense is most helpful to programmers and program maintainers.
|
|The reasoning goes like this -- (1) there's LOTS of things that a
|compiler might want to know about the behavior of a subroutine, (2)
|and it isn't clear that "const" is the most important of them, (3)
|adding keywords or abusing combinations of existing keywords to get
|the additional information is likely to result in confusing cruft
|irrelevant to the correctness of the program (much like "register" in
|the old days).  The choice of what is best to know about a program
|could well vary from processor to processor or from compiler to
|compiler, so it isn't clear that this should be standardized just yet.
|Thus, don't make it part of a language that is being standardized.
....

This is fine -- if C++ [as a whole] is willing to move away from the
traditional "un*x" model of separate compilation, linking .h, .c files
etc.  -- Its just that lots of compromises have been made to the language
already to make it fix into this traditional C-like model of compilation
and linking.

The problem I see it, if you give the compiler all this extra #pragma
information, where does the compiler store the pragma information such
that separately compiled modules can access it?  -- I guess the #pragmas
could go into the .h files, further weakening the distinction between
interface and implementation.  [And leading to even longer .h compilation
times] Otherwise, one has to add new fields in the
.o files, or add an additional database of information kept on a
project-wide basis....

Optimizations based on const follows in a straight forward manner from const'
ness -- if compilers can rely on const on a contractual basis, and require no
information from a programmer beyond what programmer's currently are
providing.  Optimizations based on const also encourage good programming
practice of declaring const on const things.

....Alternatively, maybe its just time to admit that the C-model of separate
compilation/linking is done for, and toss out the C++ language hacks based
on those restrictions.  But please, lets not get into a worse of both
worlds situation where the language hacks remain, but other decisions are
made forcing C++ compilers towards auxiliary databases of information.




Author: jimad@microsoft.UUCP (Jim ADCOCK)
Date: 20 Aug 90 17:53:34 GMT
Raw View
In article <11194@alice.UUCP> shopiro@alice.UUCP (Jonathan Shopiro) writes:
|
|Our compromise partitions the set of types.  Meaning-wise const types
|are those with constructors or destructors or arrays of these.  (Note
|that a type with a member or base that has a constructor or destructor
|automatically has one).  The rest are bit-wise const.  An implementation
|may not put a const instance of a meaning-wise const type into
|read-only memory, and a programmer may cast const aside from a pointer
|to a meaning-wise type and be assured that the program will work as if
|the pointer and its referent had never been declared const in the
|first place.  E&S says only that const instances of bit-wise const
|types may be put into read-only memory, but I think it would be
|reasonable for X3J16 to extend this interpretation so that an
|implementation would be allowed to assume that a const pointer to a
|bitwise const type points to memory that will not change.  (Const
|volatile would tell the implementation not to make this assumption).

Such an interpretation prevents the enregistering of members across a
"const" member function.  This puts C++ at a competitive disadvantage
to other OOPLs that maintain function calls on a contractual basis.
Eventually C++ would become know as "that slow OOPL", not "that fast OOPL."
I think this would be a mistake.  Const should mean const.  Casts from
const should be at best implementation defined when they violate a
function's implied contract.




Author: twagner@madrone.berkeley.edu (Tim Wagner)
Date: 10 Aug 90 03:34:43 GMT
Raw View
The recent discussion on this newsgroup about the conflicting uses of
'const' gives one pause.  Shouldn't something as useful as the two
notions here be corrected in C++?

The key distinction is between a restriction of access through a particular
binding, and a restriction on access to an underlying object.  In the
first case, the programmer merely wants to tighten the type of a name (binding)
to get additional compile-time error-checking for what he/she has decided is
an invalid access attempt.  In the second case, the object being referred to
is truly a constant; the compiler is justified in placing it in read-only
storage, and preventing (to the extent possible) any non-read-only access
attempt through any binding at all.

For a name access restriction, casting into the equivalent non-restricted type
makes sense.
For object access restriction, casting into the non-restricted type should
produce a stern warning, since writing to such an object can produce runtime
errors depending on the implementation.

One problem that currently exists is the confusion between objects and
bindings.  Consider the following code:

int i;
const int& r = i;
...
i = 5; /* Legal */
r = 6; /* Compiler warning about assigning to non-const object */

In the second line, the 'const' essentially refers to the binding of
the name 'r', NOT to the object 'r' refers to (which is obviously non-const).

In the following code, the 'const' refers to the object AND the binding:

const int i;
int& r = i;
...
i = 5; /* Compiler warning about assigning to non-const object */
r = 6; /* No warning, and probably a runtime error */

The confusion over the meaning of 'const' is troublesome, and creates
an asymmetry in whether it applies to the object or the binding.  In
the latter case, one might very well desire a read-write object with
a read-only binding through i (but not through r).  This is not expressible
in the language per se.

One possible solution is to apply machine-independent semantics for the
keyword volatile.  That is, the following chart will obtain:

      | volatile | none
-------------------------
const |     A    |  B
-------------------------
none  |     C    |  D
-------------------------

A:  A name declared with these specifiers has a read-only access restriction
    associated with it (i.e., the name is read-only), but the underlying
    object is read/write.  Casts to B can occur implicitly; casts to
    C or D must be explicit.

B:  A name declared with only the 'const' specifier has both the read-only
    access restriction, AND the object it refers to is declared to be
read-only.
    The compiler is justified in replacing the value (where possible) with
    its value (i.e., inlining the value), caching it in a register, etc.
    Casts to A occur implicitly; casts to C or D must be explicit.

C:  This suggests to the compiler that the object cannot be held in read-only
    storage, even if it "believes" otherwise.  There may be additional
optimizing
    actions that are prevented by the addition of the "volatile" specifier.
    Casts to D are implicit; casts to A and B must be explicit.

D:  Normal type.  Casts to A,B,and C are implicit. The compiler is free to
    treat the object as read-only or read-write, depending on what sort of
    analysis it is capable of.  The binding, in any case, is read-write.

This has two advantages: it supplies a useful semantic meaning to 'volatile',
and it distinguishes between two important, but distinct, meanings of
read-only.  gcc, for instance, will (in my mind correctly) handle a
global declaration of "const volatile int i;" by creating a read-write object
(i.e., not in the text segment) with read-only access restrictions for
the name 'i'.  THIS SHOULD BE CODIFIED INTO LAW!  Furthermore, a code fragment
such as:

int i;
const int *p = &i;

should be flagged as a violation: the semantics are inconsistent here, as
the object 'p' points to is NOT const.  This should really be written

int i;
const volatile int *p = &i;

since the BINDING is read-only, rather than the object being pointed to.


The use of 'const' already confuses the issue of binding and object; the
suggested style requires 'const' to refer to the object and the binding, unless
'volatile' modifies it to refer to the binding only.  Since this appears to
be the only place where bindings and objects are treated separately already,
the change in semantics appears justified.  Furthermore, the use of
'volatile' to imply that the object is read/write is consistent with what
little semantics are described for it in E&S.  If a particular site or
implementation requires additional semantics formerly produced by 'volatile',
a new keyword or pragma may be used instead.

*******************
Tim A. Wagner
Graduate Researcher, UCB
My opinions are my own, etc.
twagner@sequoia.Berkeley.EDU
*******************




Author: sakkinen@tukki.jyu.fi (Markku Sakkinen)
Date: 10 Aug 90 11:09:39 GMT
Raw View
In article <26909@pasteur.Berkeley.EDU> twagner@madrone.berkeley.edu (Tim Wagner) writes:
>
>The recent discussion on this newsgroup about the conflicting uses of
>'const' gives one pause.  Shouldn't something as useful as the two
>notions here be corrected in C++?
> [rest of long article deleted]

Sorry, I have not seen the previous discussion.
In my ECOOP'88 paper I had a much simpler suggestion that would
be sufficient for most practical cases.

Rename "pointer to constant" as it currently stands in C++
into something like "nonmodifying pointer" and introduce
also true pointers to constant. If we call ordinary pointers
"modifying pointers", then obviously the only safe conversions are
from "pointer to constant" to "nonmodifying pointer" and
from "modifying pointer" to "nonmodifying pointer".

References can be handled analogously to pointers, of course.

Markku Sakkinen
Department of Computer Science
University of Jyvaskyla (a's with umlauts)
Seminaarinkatu 15
SF-40100 Jyvaskyla (umlauts again)
Finland
          SAKKINEN@FINJYU.bitnet (alternative network address)




Author: mckenney@sparkyfs.istc.sri.com (Paul Mckenney)
Date: 10 Aug 90 16:35:33 GMT
Raw View
In article <26909@pasteur.Berkeley.EDU> twagner@madrone.berkeley.edu (Tim Wagner) writes:
> [....]
>One possible solution is to apply machine-independent semantics for the
>keyword volatile.  That is, the following chart will obtain:
>      | volatile | none
>-------------------------
>const |     A    |  B
>-------------------------
>none  |     C    |  D
>-------------------------
>A:  A name declared with these specifiers has a read-only access restriction
>    associated with it (i.e., the name is read-only), but the underlying
>    object is read/write.  Casts to B can occur implicitly; casts to
>    C or D must be explicit.

I disagree with this interpretation; the name declared might well refer
to a register that is updated by hardware but that is not to be touched by
at least part of the software.  For example, the register might be
part of a real-time clock, and writing to the register might have
the effect of setting the clock -- not an operation to be performed
lightly!

In this case, the compiler should prohibit modifying the object referred
to by the name, but must not assume that a copy of the object still has
the same value as the object itself (since the object is subject to change
by outside agents).

Therefore, I feel that casts from A to all of B, C, and D should be explicit.


     Thanx, Paul




Author: jimad@microsoft.UUCP (Jim ADCOCK)
Date: 13 Aug 90 18:11:41 GMT
Raw View
I think the idea of using 'volatile' with 'const' to help resolve some
of const's multiple meanings is a good idea -- but I'm not sure the
other suggestions follow.  One problem I see is that there are [at least]
two reasonable interpretations that one can put on 'volative' + 'const'

1) A read-only access permission to something that can be changing.  A
read-only access permission to a clock register, for example.  One might
not want to grant read/write permission to such a register because then
anyone can change the time.

2) A statement that the internals of an object might change, but from the
public interface to the object, the object looks unchanged.  An example
would be a routine that modifies cached values in an object, such that those
values can be accessed faster in the future, but otherwise the state of
the object appears unchanged from the outside world.  This is the traditional
case where people want to cast away from const in a routine whose parameters
are declared const.

One possibility is to overload the meaning of 'const' + 'volatile' depending
on the order of the two:

const volatile vs
volatile const

I think this word ordering is enough hair splitting to cause people a
lot of trouble remembering, but yet I am loath to introduce yet-another key
word.  So I have mixed feelings about this.  Restating, and expanding the
original matrix, I get:

A) volatile const.  An object that appears const to the outside world that
may be changed internally.  An example might be an object that caches certain
values for faster access in the future.

B) const.  A strictly read-only object that doesn't change.

C) volatile.  A read/write object that may change 'of its own accord.'
This could include changes made via non-portable coding hacks.
A compiler shouldn't apply optimizations that assume the object is going
to stay the same.

D) none.  A read/write object that the compiler can apply reasonable optimi-
zations to.  The object doesn't change except via legitimate accesses
within the language.  A compiler can assume that non-portable coding hacks
are not being used.

E) const volatile.  Read-only permissions to an object that may be changing
of its own accord.  A example might be a clock register to which write
permissions need to be denied, because people shouldn't be allowed to change
the time.  Compilers can't optimize.

"Safe" conversions that could be applied implicitly are:

D to B, C, E, A
B to E
C to A, E
A to C, E
E to none-of-the-above




Author: cimshop!davidm@uunet.UU.NET (David S. Masterson)
Date: 14 Aug 90 21:19:16 GMT
Raw View
In article <56514@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes:

   A) volatile const.  An object that appears const to the outside world that
   may be changed internally.  An example might be an object that caches
   certain values for faster access in the future.

   E) const volatile.  Read-only permissions to an object that may be changing
   of its own accord.  A example might be a clock register to which write
   permissions need to be denied, because people shouldn't be allowed to
   change the time.  Compilers can't optimize.

Might this not be more easily accomplished by public/private interfaces?  In
the private interface of the object, the value is defined as volatile (or
'none').  However, the public interface would have a function that returns a
'const pointer*' to the private member data.

Also, 'volatile' and 'const' seem to differ on the key point of compiler
optimizations (the first can't be, but the second one can be).  Doesn't the
(A) and (E) definitions hurt the 'const'ness of the object from the
compilation standpoint, so making the previous paragraph a more 'desirable
mode of operation?

I am one that believes 'const' should be constant and enforced as such by the
compiler.  Casting is not a valid trick for getting around this.
--
====================================================================
David Masterson     Consilium, Inc.
uunet!cimshop!davidm    Mtn. View, CA  94043
====================================================================
"If someone thinks they know what I said, then I didn't say it!"




Author: nelson@melodian.cs.uiuc.edu (Taed Nelson)
Date: 14 Aug 90 22:48:06 GMT
Raw View
In article <56514@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes:
>
>    A) volatile const.  An object that appears const to the outside world that
>    may be changed internally.  An example might be an object that caches
>    certain values for faster access in the future.
>
>    E) const volatile.  Read-only permissions to an object that may be
changing
>    of its own accord.  A example might be a clock register to which write
>    permissions need to be denied, because people shouldn't be allowed to
>    change the time.  Compilers can't optimize.


Our project has often felt the need for a "mutable" object class, which would
  be essentially equivalent to the "volatile const" above.  I also see the
  great need for the second.

Personally, I do not think that a const --> non-const class should be allowed
  (or at least highly discouraged) for the same reason that you cannot cast
  from a register to a static storage.  But that's all been discussed.

The example where we really felt the need for something between non-const
  and const (and that being constant to the user but the object may change
  its internal state) is for objects which have a "current placeholder" type
  of field.

For example, we have a Dictionary class which is kept current by the system,
  not the user / user program.  Whenever the user wants to use the dictionary,
  we give them a constant reference to it.  This allows them to extract entries
  (which return constant references as well) since that is a const
member function.
  Sometimes, though, the user will want to iterate over the entire dictionary.
  For that reason, we provide them with various First() and Next() functions.
  Unfortunately, the "current entry" which is needed for the Next() needs to
  be changed, thus violating the "constness" of the object.

We solved this problem by providing an "iterator" class which the user uses to
  provide the Next() functions (the iterator does the storing of the state
  information), but I don't think it very clean.  Especially since it requires
  another class...




Author: shopiro@alice.UUCP (Jonathan Shopiro)
Date: 15 Aug 90 20:51:36 GMT
Raw View

The meaning of const has been discussed quite a bit around here.  I
used the term "bit-wise const" to mean that the storage may not be
changed, and "meaning-wise const" otherwise.  It is clear that both
interpretations of const are meaningful and useful, and that neither
subsumes the other.  The higher-level abstractions that C++ was
particularly designed to support require the meaning-wise
interpretation of const, but effective use of read-only memory (which
has traditionally been an important issue at AT&T) requires the
bit-wise interpretation.

Our compromise partitions the set of types.  Meaning-wise const types
are those with constructors or destructors or arrays of these.  (Note
that a type with a member or base that has a constructor or destructor
automatically has one).  The rest are bit-wise const.  An implementation
may not put a const instance of a meaning-wise const type into
read-only memory, and a programmer may cast const aside from a pointer
to a meaning-wise type and be assured that the program will work as if
the pointer and its referent had never been declared const in the
first place.  E&S says only that const instances of bit-wise const
types may be put into read-only memory, but I think it would be
reasonable for X3J16 to extend this interpretation so that an
implementation would be allowed to assume that a const pointer to a
bitwise const type points to memory that will not change.  (Const
volatile would tell the implementation not to make this assumption).

On a separate topic, I have heard there is some confusion about
Sh[ao]piro.  Jonathan Shapiro (shap@sgi.com) is a friend of mine and a
C++ expert (so we usually agree), but he is not me.
--
  Jonathan Shopiro
  AT&T Bell Laboratories, Warren, NJ  07060-0908
  research!shopiro   (201) 580-4229




Author: DEREK@AppleLink.apple.com (Derek White)
Date: 15 Aug 90 21:28:31 GMT
Raw View
In article <1990Aug14.224806.21375@brutus.cs.uiuc.edu>
nelson@melodian.cs.uiuc.edu (Taed Nelson) writes:
> The example where we really felt the need for something between non-const
> and const (and that being constant to the user but the object may change
> its internal state) is for objects which have a "current placeholder" type
> of field.
>
> For example, we have a Dictionary class which is kept current by the system,
> not the user / user program.  Whenever the user wants to use the dictionary,
> we give them a constant reference to it. This allows them to extract entries
> (which return constant references as well) since that is a const
> member function.
> Sometimes, though, the user will want to iterate over the entire dictionary.
> For that reason, we provide them with various First() and Next() functions.
> Unfortunately, the "current entry" which is needed for the Next() needs to
> be changed, thus violating the "constness" of the object.
>
> We solved this problem by providing an "iterator" class which the user
> uses to provide the Next() functions (the iterator does the storing of the
> state information), but I don't think it very clean.  Especially since it
> requires another class...

I think the iterator solution is very clean.  Seperate iterator classes
allow multiple iterations over the same collection.  They also neatly
divide the job of iterating, and as you have shown, they pull out the
variable part of a constant object.

In fact, the recent examples that have shown a need for "partially const"
objects have fallen in the same catagory:  I think they can be solved by
seperating the constant and variable portions of an object into constant
and varying fields or classes.

Although it may be expedient to make a statement that an object is const
when it really isn't, I think in the long run honesty is the best policy.
I suggest a hard line approach: const is constant.


Derek White                          AppleLink: DEREK
              - Standard Discliamer -




Author: shopiro@alice.UUCP (Jonathan Shopiro)
Date: 16 Aug 90 15:24:56 GMT
Raw View
In article <11194@alice.UUCP>, I wrote:
>
>
> ...  E&S says only that const instances of bit-wise const
> types may be put into read-only memory, but I think it would be
> reasonable for X3J16 to extend this interpretation so that an
> implementation would be allowed to assume that a const pointer to a
> bitwise const type points to memory that will not change.
>
Oops!!  Consider the following perfectly reasonable function:

 void
 increase(int* ip, const int* cip)
 {
  *ip += *cip;
 }

and a call to the function:

 main()
 {
  int  i = 3;
  int*  p = &i;
  const int* cp = &i;
  increase(p, cp);
  cout << *cp << "\n";
 }

This function had better print "6", but if my unthinking proposal
were accepted, it would be permissible for it to print "3."  Of
course, in this case, the aliasing is obvious, but in general
aliasing is impossible to detect at compile time.

I would be willing to consider allowing the implementation to assume
that memory pointed to by a const pointer to a bitwise const type
points to memory that will not change, but only if the implementation
can prove that the memory cannot be changed through any legally
constructed alias.  (For example the pointer points to an automatic
variable in that function and the address of that variable has not
been saved elsewhere).

On a separate topic, I have changed my .signature but I am still the
same person.
--
  Jonathan E. Shopiro
  AT&T Bell Laboratories, Warren, NJ  07059-0908
  shopiro@research.att.com   (201) 580-4229