August 18, 2003
> Temporaries, generated in C++ expressions, are const. This has to be to insure they can be cleaned up correctly. That is, making a function work with const, makes it more flexible in respect to temporaries. I can recall similar rules for some circumstances in (IIRC) Delphi and certainly Sather.

Nope, whether something's const or not doesn't change a bit about how it's cleaned up. There are two cases in which const makes a difference:

1. Temporaries are const so they cannot be passed by reference, but by
   const reference. This is mainly a convenience thing, while forbidding
   references to temporaries is a style issue - references to temporaries
   was considered to cause many problems when it was still allowed. Don't
   know whether it was a really big issue or not though, wasn't using C++
   at the time :)
2. For some data structures, certain optimizations can be made when it's
   known that the data structure isn't changed during traversal; so for
   certain classes calling functions with const parameters or on const
   objects will cause completely different code to be executed than without.
   This can cause both notable performance advantages and notable headaches
   during debugging when you're not expecting it. :)

> And i still don't think i understand, what's the sense of casting away const-ness - we have our mutable fields. Can anyone come up with a sane example?

Casting away const-ness should be outright forbidden and done away with, because as I already argued it renders the whole const qualifier into just a vague promise. However mutable is relatively recent, so I guess const_cast is still in C++ for backwards-compatibility issues (like so many things).

-fg


August 18, 2003
In article <bhqmei$l2q$1@digitaldaemon.com>, Fabian Giesen wrote:
> Casting away const-ness should be outright forbidden and done away with, because as I already argued it renders the whole const qualifier into just a vague promise. However mutable is relatively recent, so I guess const_cast is still in C++ for backwards-compatibility issues (like so many things).

"Dag Brück and others reviewed considerable amounts of real code to see
which casts were casting away const and which of those could be
eliminated using 'mutable'. This study confirmed the conclusion that
"casting away 'const'" cannot be avoided in general and that
'mutable' appears to eliminate casting away 'const' in less than half of
the cases where it is needed in the absence of 'mutable'."

D&E, §13.3.3

-Antti

August 18, 2003
Antti Sykäri wrote:
> "Dag Brück and others reviewed considerable amounts of real code to see
> which casts were casting away const and which of those could be
> eliminated using 'mutable'. This study confirmed the conclusion that
> "casting away 'const'" cannot be avoided in general and that
> 'mutable' appears to eliminate casting away 'const' in less than half of
> the cases where it is needed in the absence of 'mutable'."

That's about changing existing code - which might be unreasonable...

When designing new code, things are different. There is an opinion, that when someone casts away const-ness, this means illogical design which can be avoided from the beginning on. I don't have enough experience to say whether it's true or not, but i would like to think that this statement is true. I'm looking for counter-examples: maybe anyone can give me a hint?

-eye

August 18, 2003
Perfectly put! I agree.


"Antti Sykäri" <jsykari@gamma.hut.fi> wrote in message news:slrnbjvjf1.pru.jsykari@pulu.hut.fi...
> In article <bho1ia$2ro1$1@digitaldaemon.com>, Mike Wynn wrote:
> >
> > "Antti Sykäri" <jsykari@gamma.hut.fi> wrote in message news:slrnbjuvvn.man.jsykari@pulu.hut.fi...
> >> In article <bhmc8c$h12$1@digitaldaemon.com>, Fabian Giesen wrote:
> >> >> So the standard says that if we've got pointer to a const object, we can't change it, but does not indeed say the object would be immutable. Which is quite convenient: when you call a function with signature void f(const T*); you can be certain that it won't change your argument.
> >> >
> >> > Unless someone casts your donstness away, which anyone can do without you ever knowing.
> >> >
> >> > Which means that const is really just a vague promise.
> >>
> >> You can be pretty certain that the callee won't cast your constness
away
> >> without being sure that the object isn't actually const-qualified,
since
> >> the object could be const-qualified and located in a read-only segment. If it is, trying to modify it through a non-const pointer will cause undefined behavior -- in practice, segmentation fault.
> >>
> > I'm not sure a quite follow the argument here, and not all platforms seg
> > fault they may quitely not change things (Rom'ed object on an embedded
> > target).
> >  in all you are just justifying the point that c++ const is a
meaninlessly
> > vague promise.
> > what it wanted is a concrete callee promise that they will not modify
under
> > any condition
> > (the caller or other may [which is the root of the problem])
>
> It's just a question of the proportion of trust you are ready to place on the contract (or the promise) that the function declaration "f(const T*)" has. "I won't modify my argument."  The const keyword is a way to state that clearly and concisely.  If you would want to ban const_cast to make that a "concrete guarantee" instead of a promise, you'd have to ban unions, inline assembly, foreign function interfaces and all those good old dangerous features, because they can all be used to subvert constness.
>
> As for the "vague promise" that const keyword gives...
>
> Is it, by analogy, a "vague promise" that you will end up in jail if you commit a murder?  You might get away with it (if the police don't catch you or if you happened to cast away the constness of an object that actually wasn't const) or then you might get caught (if the object actually was in a read-only segment).
>
> People don't usually go around killing other people, firstly because usually there's no particular reason to do that.  Secondly, doing that might have dire consequences -- undefined behavior if you will.  And you don't break the unspoken rules of a programming language either, or if you do, you face the consequences.
>
> I'm not going to give any reasons why it would be a good idea for anyone to kill someone (we already had a religious discussion about goto; no need to bring abortion, euthanasia or death penalty into the picture now), but sometimes it's needed to cast away the constness and therefore C++ has standard, working, well-documented const_cast operator for that purpose.
>
> Anyway, my point, if it didn't state it clearly enough, was that no one in their sane mind would do, for example, this:
>
> cheater.h:
> --------------------------
> // I promise not to touch str
> void cheater(const char* str);
> --------------------------
>
> cheater.cpp:
> --------------------------
> void cheater(const char* str)
> {
>         char* cheat = const_cast<char*>(str);
>
>         // Ha-ha! A little trick, hopefully no one will notice.
>         cheat[0] = 'x';
> }
> --------------------------
>
> The reason being:
>
> main.cpp:
> --------------------------
> #include "cheater.h"
> #include "stdio.h"
>
> int main(int argc, char* argv[])
> {
>         if (argc < 2)
>                 return 1;
>
>         const char* str;
>
>         if (strcmp(argv[1], "1") == 0)
>         {
>                 const char const_string[] = "abc";
>                 str = const_string;
>         }
>         else if (strcmp(argv[1], "2") == 0)
>         {
>                 char non_const_string[] = "abc";
>                 str = non_const_string;
>         }
>         else if (strcmp(argv[1], "3") == 0)
>         {
>                 str = "abc";
>         }
>
>         cheater(str);
>         printf("str = %s\n", str);
> }
> --------------------------
>
> jsykari:~% mv a.cc main.cc
> jsykari:~% g++ main.cc -o main
> jsykari:~% ./main 1
> str = xbc
> jsykari:~% ./main 2
> str = xbc
> jsykari:~% ./main 3
> zsh: segmentation fault  ./main 3
>
> Whoops!
>
> One of the general rules that guided the development of C++ was "Don't try to force people" (quote from D&E):
>
> "Programmers are smart people. They are engaged in challenging tasks and need all the help they can get from a programming language as well as from other supporting tools and techniques. Trying to seriously constrain programmers to do "only what is right" is inherently wrongheaded and will fail. Programmers will find a way around rules and restrictions they find unacceptable."
>
> I hope that D is not heading in a radically different direction.
>
> Oh, and by the way, same applies for the dreaded goto statement.
>
> -Antti
>


August 18, 2003
> As for the "vague promise" that const keyword gives...
>
> Is it, by analogy, a "vague promise" that you will end up in jail if
> you commit a murder?  You might get away with it (if the police don't
> catch
> you or if you happened to cast away the constness of an object that
> actually wasn't const) or then you might get caught (if the object
> actually was in a read-only segment).
>
> People don't usually go around killing other people, firstly because
> usually there's no particular reason to do that.  Secondly, doing that
> might have dire consequences -- undefined behavior if you will.  And
> you don't break the unspoken rules of a programming language either,
> or if
> you do, you face the consequences.

This is beside the point of what I'm trying to say. The question is why
there is a compelling need for const. I only see an use for const if it's an
actual guarantee and the compiler can rely on it and act accordingly (put
all const data into readonly segments, assume that anything declared const
is really constant for its whole lifetime). In C++, it can't, which is why I
don't see much point with doing const like it is in C++. If the language
supports
this kind of interface specifications, but cannot make use of it or enforce
correct usage, I don't see the reason for adding the specification in the
first place. That would be like adding an inout_cast to make "in" parameters
inout in certain cases.

I agree that such limitations can always be worked around with inline assembler or union hacks or stuff like that, but that's not of interest to me; if you have to go into the realm of undefined behavior in the first place to do something, it's perfectly okay if you get undefined behavior in return. :)

As for const, that's a software design issue IMHO. If you add const, then make
it rigid. Mutables are okay, because those are also part of the interface
specification and thus also documented and acceptable. Functions that claim they
have const objects and still modify them aren't, because in that case the
interface specification mismatches the actual interface. All uses of
const_cast I've seen so far in C++ code (with C++ compilers that did support
mutable) were basically quick&dirty hacks because of people either not wanting
to change the interface to get a non-const parameter or people not wanting to
make variables mutable and suffer LONG recompile times in big projects because
a central header changed. The second is purely a problem of the C/C++
compilation
model and not relevant in that way to D; and the first is something a language
that employs design by contract should prevent. After all, modifying a variable
that's supposed to be const is a far more basic violation of the interface
specification and contract than returning a wrong value in 0.1% of all cases :)

-fg


August 19, 2003
IMO, if the default was const, the situation would be a bit better... since forgetting the modifier would be catched as soon as someone try to modify something instead of waiting till someone try to pass a const something where a modifiable object is expected.

I think that const is clearly desirable for pointers to struct, intergral type, other pointers (multi-level indirection) and enumeration.

For class object, I think it is a bit less usefull and a bit more painfull
since for member functions we could need both cases particulary
if we want to returns a pointer (reference) to a sub-object
(or a container element).... but OTOH const in those case
in very usefull as we can provide different behavior (direct
access vs a copy) for optimisation purpose... and it allows
us tio ensure that at the same time we can prevent copy and
modification of a given object...

I also agree that in well designed code, const_cast should not be necessary at all. The problem is often in libraries where some const are missing and we try to uses them from correct code where const is not missing...

I think that the best would be that we have a way to force the compiler but by default the compiler could be smarter (i.e. verify itself if something is modified) in m any cases.

I do think that in, inout and out will help solve most of the
problem related with constness as by default parameters
are in (which should imply either by value or const reference)

"Ilya Minkov" <midiclub@8ung.at> a écrit dans le message de
news:bhrhij$1suj$1@digitaldaemon.com...
Antti Sykäri wrote:
> "Dag Brück and others reviewed considerable amounts of real code to see
> which casts were casting away const and which of those could be
> eliminated using 'mutable'. This study confirmed the conclusion that
> "casting away 'const'" cannot be avoided in general and that
> 'mutable' appears to eliminate casting away 'const' in less than half of
> the cases where it is needed in the absence of 'mutable'."

That's about changing existing code - which might be unreasonable...

When designing new code, things are different. There is an opinion, that when someone casts away const-ness, this means illogical design which can be avoided from the beginning on. I don't have enough experience to say whether it's true or not, but i would like to think that this statement is true. I'm looking for counter-examples: maybe anyone can give me a hint?

-eye


August 19, 2003
"Fabian Giesen" <rygNO@SPAMgmx.net> wrote in message news:bhrn8p$251q$1@digitaldaemon.com...
> > As for the "vague promise" that const keyword gives...
> >
> > Is it, by analogy, a "vague promise" that you will end up in jail if
> > you commit a murder?  You might get away with it (if the police don't
> > catch
> > you or if you happened to cast away the constness of an object that
> > actually wasn't const) or then you might get caught (if the object
> > actually was in a read-only segment).
> >
> > People don't usually go around killing other people, firstly because
> > usually there's no particular reason to do that.  Secondly, doing that
> > might have dire consequences -- undefined behavior if you will.  And
> > you don't break the unspoken rules of a programming language either,
> > or if
> > you do, you face the consequences.
>
> This is beside the point of what I'm trying to say. The question is why there is a compelling need for const. I only see an use for const if it's an actual guarantee and the compiler can rely on it and act accordingly (put all const data into readonly segments, assume that anything declared const is really constant for its whole lifetime).

I don't think it needs to be a guarantee. I look at const more as a domumentation
 feature of language with a few good sideeffects:
1) library optimizations possible
2) support for proxy generation is more efficient (you do not need to marshal
   const references both ways)
3) may be some compiler optimizations too

The documentation feature is the most important. I express what is my intention
 by placing there const. Also comments are not guarantee that the code really
 does what is written in them. Anyway most porgrammers think comments
 are good (or am I naive here?).
Without const your input only reference type argument is not really input,
 but in-out (or something in between) and you do not have any help from
 compiler here at all.
Full const is nice, but probably useless if compiler does not report errors/warnings
 on places where const should be put, but was not in the actual code ... or
 some other help in this matter. Programmers are too lazy.


August 19, 2003
>
> I don't think it needs to be a guarantee. I look at const more as a
domumentation
>  feature of language with a few good sideeffects:
> 1) library optimizations possible
> 2) support for proxy generation is more efficient (you do not need to
marshal
>    const references both ways)
> 3) may be some compiler optimizations too
>
> The documentation feature is the most important. I express what is my
intention
>  by placing there const. Also comments are not guarantee that the code
really
>  does what is written in them. Anyway most porgrammers think comments
>  are good (or am I naive here?).
> Without const your input only reference type argument is not really input,
>  but in-out (or something in between) and you do not have any help from
>  compiler here at all.
> Full const is nice, but probably useless if compiler does not report
errors/warnings
>  on places where const should be put, but was not in the actual code ...
or
>  some other help in this matter. Programmers are too lazy.
>
>

I agree with that... Maybe for library implementation, it could be usefull to have keyword (or attributes) that would better control what it is allowed...

For ex. a function parameter might be declared "immuable" or "strict const"
to tell the compiler that it cannot be modified under any circumpstance.
Personnaly, I think that extra attributes (as in IDL and .NET) could be
uses to write highly optimized library but would not be used in typical user
program. This could be compared to some advanced optimisations in C++
with boost, move constructors, and compiler traits (is_class, is_enum,
is_POD,...) that allows to make the STL more efficients.



August 19, 2003
In article <bhrn8p$251q$1@digitaldaemon.com>, Fabian Giesen wrote:
>> People don't usually go around killing other people, firstly because [ ... ]
> 
> This is beside the point of what I'm trying to say. The question is why there is a compelling need for const. I only see an use for const if it's an actual guarantee and the compiler can rely on it and act accordingly (put all const data into readonly segments, assume that anything declared const is really constant for its whole lifetime).

Point taken. I didn't particularly try to advocate "const" as it is in C++, just wanted to point out that while it might play a role of a vague promise to the compiler, this is not the case for the programmer (and, importantly, maintainer), who enjoys the benefits of increased type information.

I'm not sure if const is at all needed. Personally I've been a happy user of const ever since I learned C++ and haven't really tried to live without const (with the exception of occasional straying to the Java side). So I'd rather trust the opinions of the more experienced programmers. Meanwhile, let us concentrate for a moment on the meaning of const.

Conceptually, the const as we know it in C++ offers a read-only access to the object. If we leave basic types and structs out of the picture, and just look at classes, we can implement it by separating the class' interface into read-only interface and the rest. If the class is already accessed via virtual functions (like a proper class should), this doesn't even impose any extra costs. "Const" access to the class can be provided by explicitly returning the read-only interface of the class, and this is in fact what happens when you specify a "const T" in C++: you actually get an object of type T, but can effectively access only the subset of member functions which are explicitly marked "const".

This is also an issue that needs to be taken into consideration when designing the basic container library for D.

Java, a blatant mockery of static typing, solves the "const" by providing a view to the container (via java.util.Collections.unmodifiableCollection or similar) which looks exactly like the original, but throws an UnsupportedOperationException when one tries to modify it.  No wonder there's a project trying to bring "const" to Java (http://pag.lcs.mit.edu/constjava/). At any case, if the language has no const and someone wants non-writable containers, (and someone definitely will), the library designer must balance between proliferation of const interfaces and the risk of run-time errors. In C++ he could just leave the complication up to the language.

Oh, and then there are the basic types which are left without any protection. But I suppose one can get away with some kind of boxing. And nobody wants to pass small values by const-qualified pointers anyway, so they are kind of non-issue.

As a side note, "const" was originally proposed in 1981 and was called "readonly", and there was also "writeonly". (To mirror the properties of r/w bits in the memory controller; possibly memory-mapped hardware registers) The standardization process changed "readonly" to "const" and dropped "writeonly".

> As for const, that's a software design issue IMHO. If you add const, then make it rigid. Mutables are okay, because those are also part of the interface specification and thus also documented and acceptable.

So assume that we'd have these kind of strictly constant / rigidly constant / guaranteed to have the same value objects. "immutable" would not be a bad term, IMO, so I'll use it from now on.

I can distantly see some consequences:

- compiler could probably do some optimizations better

- object of type T cannot be assigned to variable of type immutable T;
  to produce an immutable T you either have to clone it or have it
  be immutable from the beginning

- there *will* be cases where the programmer wants to cast a T to
  immutable T because he simply knows that the object won't change.
  Should a simple cast like ((immutable T) t) suffice?

- there would have to be methods with immutable modifier, which would
  comprise the immutable object's interface

- plus the added complexity of overloading + other stuff that Walter has
  used as an argument against const

All of this would complicate the language somewhat; but probably only after implementing and experimenting you would know whether it would be worth it.

Are there any languages out there (except the purely functional ones)
with immutable values?

Now that I think of it, I remember that Daniel Yokomiso wrote an interesting description of const stuff some time ago, let's see... There, I see it's still worth reviewing: http://www.digitalmars.com/drn-bin/wwwnews?D/9962

(Daniel: how's Eon doing, by the way?)

-Antti
August 20, 2003
"Antti Sykäri" <jsykari@gamma.hut.fi> a écrit dans le message de news:slrnbk5c5l.4q6.jsykari@pulu.hut.fi...
> In article <bhrn8p$251q$1@digitaldaemon.com>, Fabian Giesen wrote:
> >> People don't usually go around killing other people, firstly because [ ... ]
> >
> > This is beside the point of what I'm trying to say. The question is why there is a compelling need for const. I only see an use for const if
it's an
> > actual guarantee and the compiler can rely on it and act accordingly
(put
> > all const data into readonly segments, assume that anything declared
const
> > is really constant for its whole lifetime).
>
> Point taken. I didn't particularly try to advocate "const" as it is in C++, just wanted to point out that while it might play a role of a vague promise to the compiler, this is not the case for the programmer (and, importantly, maintainer), who enjoys the benefits of increased type information.
>
> I'm not sure if const is at all needed. Personally I've been a happy user of const ever since I learned C++ and haven't really tried to live without const (with the exception of occasional straying to the Java side). So I'd rather trust the opinions of the more experienced programmers. Meanwhile, let us concentrate for a moment on the meaning of const.
>

I do think that we need some kind of const access weither it is usefull or not for the compiler. It is usefull for the programmer. Making it strictier would make it even more usefull but library writers would have to do it right!

>
> > As for const, that's a software design issue IMHO. If you add const, then make it rigid. Mutables are okay, because those are also part of the interface specification and thus also documented and acceptable.
>
> So assume that we'd have these kind of strictly constant / rigidly constant / guaranteed to have the same value objects. "immutable" would not be a bad term, IMO, so I'll use it from now on.
>
> I can distantly see some consequences:
>
> - compiler could probably do some optimizations better
>
> - object of type T cannot be assigned to variable of type immutable T;
>   to produce an immutable T you either have to clone it or have it
>   be immutable from the beginning
>

So your definition of immuable that an object won't changes... but for a function parameter, does it apply to both the source and target or only to the target (as const in C++).

> - there *will* be cases where the programmer wants to cast a T to
>   immutable T because he simply knows that the object won't change.
>   Should a simple cast like ((immutable T) t) suffice?
>
> - there would have to be methods with immutable modifier, which would
>   comprise the immutable object's interface
>
> - plus the added complexity of overloading + other stuff that Walter has
>   used as an argument against const

For overloadding, we should then have a way to reuse the same code for all variations if applicable.

typical case would be to be able to select the appropriate constness of the return value of a member function...

I think that the compiler could automatically make the result const if this is required (for ex. when returning an element from a const container).

class E;

class C {
    E &get() { return member; }

    E member;
}

Here if get is called on a const C, the compiler could add const to E if otherwise the function would compile if it were const.

Doing it that way would avoid most of the complexity of overloadding in C++ where we need to provide both a const and a regular version of the same function.

Also, the programmer won't be required to put all const... The compiler would be able to do some analysis to verify if a function can be generated.

And with prohibited keyword that I suggest in another thread, one would be
able to prohibit using the const version if he wants (for example for a swap
function, we don't want const parameter and prohibiting it would do
that the compiler won't have to continue analysis...)

I would opt for smart constness and a few modifier when they are required. I would add prohibited and immuable and borrow const and mutable from C++...

prohibited would be a function modifier that will ensure that the function is never called.

immuable would be a parameter modifier that would be more strict than
const (no const_cast possible)

>
> All of this would complicate the language somewhat; but probably only after implementing and experimenting you would know whether it would be worth it.
>

>
> -Antti