September 19, 2003 Re: c++ style const concept | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthew Wilson | "Matthew Wilson" <matthew@stlsoft.org> wrote in message news:bkdt7v$1vih$1@digitaldaemon.com... > Yesterday you raised the issue of the deblank() function having the wrong semantics. If we had a readonly keyword in D, the issue would be moot. Not exactly. Consider the case of passing a parameter that is int****p. If it is 'readonly', what part of it is readonly? p? *p? **p? ***p? ****p? all of them? To resolve the issue with deblank(), more than just the string reference (i.e. p) would have to be readonly. > I want code to be self-documenting, and the compiler to help enforce that (to a reasonable degree). If we had "readonly", that could be achieved. I don't give a fig for optimisations based on putative vs actual read-only, and all that other guff, and will be thoroughly unperturbed if that is left > out as it stands currently. But I remain strongly unconvinced that its absence from D is a +ve step. I'd be very interested to hear anyone to put forth an argument for such in response to what I (and others, who've commented similarly) want from a readonly/const keyword, rather than countering with the optimisation arguments. Fair enough, and I had given some earlier in this thread <g>. Let's discuss the one about self-documentation. I agree with you that code should be self-documenting, as I've argued that comments are invariably missing, out-of-date, incomplete, or wrong. The trouble with const being self-documenting is like checked exceptions in Java. Java issues a compile error if you call a function that throws something not listed in the exception specification. So, adding functionality to a function can entail going back through the entire static call chain editting all the exception specifications - so annoying that too many Java programmers, even good ones, tend to write try{f.foo();}catch{} just to shut up the compiler and get on with it. This, of course, completely subverts exception specifications and makes it far worse than not having exception specifications at all. (Even worse, despite being "exception specification correct", it is still possible to get exceptions not listed.) Const has similar problems. You can't just ignore const if it is in the language, as you'll need to inevitably interface with code that uses it. The shortest, easiest way to do it is to just throw in a few const_cast's and move on. Even worse, as I pointed out, there are legal, defined ways to pull the rug out from under const without using undefined behavior of unions, casts, inline assembler, etc. While the situation isn't near as bad as with exception specifications, the self-documenting nature of it isn't at all reliable. That said, there is a solution for const as a storage class. If it is put in read-only memory, it is const. No way around it, since the checking happens in hardware at runtime rather than compile time <g>. |
September 19, 2003 Re: c++ style const concept | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | In article <bkeah6$2k5u$1@digitaldaemon.com>, Walter wrote: > The trouble with const being self-documenting is like checked exceptions in Java. Java issues a compile error if you call a function that throws something not listed in the exception specification. So, adding functionality to a function can entail going back through the entire static call chain editting all the exception specifications - so annoying that too many Java programmers, even good ones, tend to write try{f.foo();}catch{} just to shut up the compiler and get on with it. This, of course, completely subverts exception specifications and makes it far worse than not having exception specifications at all. (Even worse, despite being "exception specification correct", it is still possible to get exceptions not listed.) > > Const has similar problems. You can't just ignore const if it is in the language, as you'll need to inevitably interface with code that uses it. The shortest, easiest way to do it is to just throw in a few const_cast's and move on. Even worse, as I pointed out, there are legal, defined ways to pull the rug out from under const without using undefined behavior of unions, casts, inline assembler, etc. While the situation isn't near as bad as with exception specifications, the self-documenting nature of it isn't at all reliable. This is a good summary of the similarities of const and exception specifications. But then we need to concentrate on the differences between them. - const is much more lightweight because it's just one bit of information in the interface. And you often get it right the first time. Even if you don't, you need to go through the call chain only once when you decide to add it. Exception specifications, on the other hand, can grow and grow, and (if you want to do it right) you have to traverse the call chain every time when you add an exception. - const affects the function's semantics directly. It tells what it can do with its arguments. This is unlike exception specifications, which might not even have anything to do with the function that they pass through. -Antti |
September 19, 2003 Re: const / immutable (was: C++ style const concept) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Philippe Mori | "Philippe Mori" <philippe_mori@hotmail.com> wrote in message news:bid8ts$12qg$1@digitaldaemon.com... > > D has deprecated: http://www.digitalmars.com/d/attribute.html > But does it is possible to control in which module or on some other condition when deprecated take effects. No. It applies to any use of a function. > Also if the attribute can be depedant on other things (probably on versioning), then it might be possible to uses version for that purpose... That might work. > > class X { } > > > > template (Foo) { > > // your general template code goes here > > } > > template (Foo : X) { > > compileTimeError("You shouldn't instantiate Foo with types derived " > > "from X"); > > } > > > > Upon finding an "instance Foo(X)" the compiler would blurt out something > like > > > > line 567: Cannot instantiate Foo(X) > > line 123: compileTimeError: You shouldn't instantiate Foo with types > > derived from X > > > > Compile time error is a must... This allows to check many constraints that are not directly supported by the language (like your example). > > This can be used to validate some constants to ensure no accidental > changes would be done. This include some magic numbers, the size > of a structure (it's alignment, member offset,...) and we should be able > also to check some properties of classes and struct like: This is now done with a new feature, static asserts. |
September 19, 2003 Re: c++ style const concept | ||||
---|---|---|---|---|
| ||||
Posted in reply to Antti Sykäri | "Antti Sykäri" <jsykari@gamma.hut.fi> wrote in message news:slrnbmlrr3.hfa.jsykari@pulu.hut.fi... > This is a good summary of the similarities of const and exception specifications. > > But then we need to concentrate on the differences between them. > > - const is much more lightweight because it's just one bit of > information in the interface. And you often get it right the first > time. Even if you don't, you need to go through the call chain only > once when you decide to add it. Exception specifications, on the > other hand, can grow and grow, and (if you want to do it right) you > have to traverse the call chain every time when you add an exception. If you add a const to a type, that can ripple downwards through the call chain, affecting a lot of functions that are quite irrelevant. Inevitably, one of those rippled functions will be modifying its argument. This has happened to me :-(. There's a powerful temptation to just put in a const_cast and forget about it rather than reengineer. > - const affects the function's semantics directly. It tells what it can > do with its arguments. This is unlike exception specifications, which > might not even have anything to do with the function that they pass > through. I agree that the const problem isn't nearly as bad as the exception specification one. |
September 19, 2003 Re: c++ style const concept | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | > > This is a good summary of the similarities of const and exception specifications.
> >
> > But then we need to concentrate on the differences between them.
> >
> > - const is much more lightweight because it's just one bit of
> > information in the interface. And you often get it right the first
> > time. Even if you don't, you need to go through the call chain only
> > once when you decide to add it. Exception specifications, on the
> > other hand, can grow and grow, and (if you want to do it right) you
> > have to traverse the call chain every time when you add an exception.
>
> If you add a const to a type, that can ripple downwards through the call chain, affecting a lot of functions that are quite irrelevant. Inevitably, one of those rippled functions will be modifying its argument. This has happened to me :-(. There's a powerful temptation to just put in a const_cast and forget about it rather than reengineer.
>
> > - const affects the function's semantics directly. It tells what it can
> > do with its arguments. This is unlike exception specifications, which
> > might not even have anything to do with the function that they pass
> > through.
>
> I agree that the const problem isn't nearly as bad as the exception specification one.
>
IMO the problem in C++ is the fact that we have to explictly
add const (for member functions) and not the other ways so it
is easy to forgot it and (and this will happen in a third-party library
you don't want to change)... so my opinion is that member function
(and in parameter) should be const by default...
That way most of the changes caused by an initial forgotten const would be avoided...
const does have its used to validate code... and to ensure that
an object would not be (reasonably) modified. In fact, if we
knows an object should not be modified, we uses const and
the compiler will issue an error if we accidently try to call a
function that modify the object.
Maybe, we should support constness only on predefined types,
enumerations, pointers, struct and class that are final (no virtual
members) and uses a constant interface for classes if we want
to prevent modifications:
interface Reader { } // Only read
interface Writer : Reader { } // Modify object
class MyClass : Reader, Writer { } // Actual class
void f(Reader r) { }
void g(Writer w) { }
MyClass c;
f(reader);
Reader rc = c;
g(rc); // Compile-time error
So my opinion is that we should have const but modify
it a bit to avoid the common pitfall of C++ (forgetting a
const on a method). For parameter, D is already better
that C++ since it has in, out and inout.... with the proper
default (i.e. in --- assuming in means const).
|
September 19, 2003 Re: c++ style const concept | ||||
---|---|---|---|---|
| ||||
Posted in reply to Philippe Mori | "Philippe Mori" <philippe_mori@hotmail.com> wrote in message news:bkg1k3$q8b$1@digitaldaemon.com... > > > This is a good summary of the similarities of const and exception specifications. > > > > > > But then we need to concentrate on the differences between them. > > > > > > - const is much more lightweight because it's just one bit of > > > information in the interface. And you often get it right the first > > > time. Even if you don't, you need to go through the call chain only > > > once when you decide to add it. Exception specifications, on the > > > other hand, can grow and grow, and (if you want to do it right) you > > > have to traverse the call chain every time when you add an exception. > > > > If you add a const to a type, that can ripple downwards through the call chain, affecting a lot of functions that are quite irrelevant. Inevitably, > > one of those rippled functions will be modifying its argument. This has happened to me :-(. There's a powerful temptation to just put in a const_cast and forget about it rather than reengineer. > > > > > - const affects the function's semantics directly. It tells what it can > > > do with its arguments. This is unlike exception specifications, which > > > might not even have anything to do with the function that they pass > > > through. > > > > I agree that the const problem isn't nearly as bad as the exception specification one. > > > > IMO the problem in C++ is the fact that we have to explictly > add const (for member functions) and not the other ways so it > is easy to forgot it and (and this will happen in a third-party library > you don't want to change)... so my opinion is that member function > (and in parameter) should be const by default... > > That way most of the changes caused by an initial forgotten const would be avoided... > > const does have its used to validate code... and to ensure that > an object would not be (reasonably) modified. In fact, if we > knows an object should not be modified, we uses const and > the compiler will issue an error if we accidently try to call a > function that modify the object. > > Maybe, we should support constness only on predefined types, > enumerations, pointers, struct and class that are final (no virtual > members) and uses a constant interface for classes if we want > to prevent modifications: > > interface Reader { } // Only read > interface Writer : Reader { } // Modify object > > class MyClass : Reader, Writer { } // Actual class > > void f(Reader r) { } > void g(Writer w) { } > > MyClass c; > f(reader); > > Reader rc = c; > g(rc); // Compile-time error > > So my opinion is that we should have const but modify > it a bit to avoid the common pitfall of C++ (forgetting a > const on a method). For parameter, D is already better > that C++ since it has in, out and inout.... with the proper > default (i.e. in --- assuming in means const). in does not mean const. The in/out/inout applies to the parameter (reference) whereas the readonly applies to the object. They're quite different. (I'm not calling it const, because "const" sucks as a term, and if D gets a "readonly" this will enable it to forgoe many of the problems with const without being accused of overlooking something) |
September 20, 2003 Re: c++ style const concept | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthew Wilson | > > So my opinion is that we should have const but modify > > it a bit to avoid the common pitfall of C++ (forgetting a > > const on a method). For parameter, D is already better > > that C++ since it has in, out and inout.... with the proper > > default (i.e. in --- assuming in means const). > > in does not mean const. The in/out/inout applies to the parameter (reference) whereas the readonly applies to the object. They're quite different. I should have said implies... An in parameter should not be modified inside a function (and if const support is eventually added to the language, it should be the default for in parameters... and otherwise it should be undefined what happen if we change a in parameter (the change may or may not be visible to the caller depending on werither a copy was made (a bit like in parameter in COM programming... If a proxy is used (remote call), then the change will not be visible and otherwise we should make changes... > > (I'm not calling it const, because "const" sucks as a term, and if D gets a > "readonly" this will enable it to forgoe many of the problems with const without being accused of overlooking something) > const and readonly are different concept... as generaly used. Typically by const, we want to talk about a C++ style constness (logical) while when readonly is used, we want to talk about hardware style readonly (physical). Ideally both concept should be exprimable with proper construct... I would like a language that would allows to express more such concepts than C++ but it seems that we make tradeoffs... we have added some new stuff (design by contract, static assertion, ...) but OTOH, we remove some usefull things, IMHO, that where present in C++... I would prefer to have more even if not everybody uses everything... |
November 03, 2003 Re: c++ style const concept | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | Walter wrote: > The problem is that the standard doesn't preclude anyone *else* from > changing the const data. For example: > > void f(int *p1, const int *p2) > { > int i = *p1; > (*p2)++; ^^^^^^^ Er, what? The integer pointed to by p2 cannot be modified when accessed through p2. At least that's what the FAQ says. When looking at the ANSI C++ spec, i cannot figure anything out. It's apparently been written by people not at the peak of comprehesibility. The DMC agrees with me. Where is a step which assigns to *p2 without casting away const-ness one or another way? What is a standard compliant way which would not result in undefined behaviour? And in which cases does const_cast exactly have well-defined behaviour? > int j = *p1; // oops! j != i > } > > int *a; > ... > f(a, a); > > This is perfectly legal and defined behavior. ????????????????????????????????????????????????????? ?? Am i going nuts or is actually something wrong ??? ????????????????????????????????????????????????????? -eye |
November 04, 2003 Re: c++ style const concept | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ilya Minkov | "Ilya Minkov" <minkov@cs.tum.edu> wrote in message news:bo6k86$2dpj$1@digitaldaemon.com... > Walter wrote: > > > The problem is that the standard doesn't preclude anyone *else* from changing the const data. For example: > > > > void f(int *p1, const int *p2) > > { > > int i = *p1; > > (*p2)++; > ^^^^^^^ > Er, what? Ah, I have it backwards. Put the const in front of p1. |
Copyright © 1999-2021 by the D Language Foundation