From: Lourens Veen on 10 Nov 2006 19:09 James Kanze wrote: > Lourens Veen wrote: > >> I'm not sure if I'm a beginner, but I don't see why this should be >> surprising: > >> const A a; // can't change a >> const B b; // can't change b >> const PtrInt pi1; // can't change pi1 > > Because that's not the way it works in general: > > const int* pi ; // can't change pi ?? For pointers, but only for pointers. For everything else it does work that way, including built-in types, class types and typedef'ed pointers. > Note that C++ declaration syntax is not easy, and putting the > const behind, rather than before, doesn't magically make it so. > I find it better, but the difference isn't necessarily enormous. > No matter where you put the const, unless the reader knows how > the declaration syntax really works, there will be cases where > it is less than obvious. Indeed. In another post, I suggested changing, or perhaps rather augmenting, pointer syntax to something like const ptr<int> x; ptr<const int> y; That would make pointer declarations similar to everything else. Function pointers could be function_ptr<void, int, int> f; for a pointer to a function returning a void and taking two ints. With variadic templates and template typedefs, this could even be defined within the language itself. I would prefer that over the current void (*f)(int, int); which I had to look up to find that my initial guess was way off. Granted, I'm sure I would have got it right if I used function pointers regularly, but I still think the above syntax would be a lot less cryptic. Sure, it's a bit more verbose than the asterisk, but if I want to avoid wearing down my keyboard I'll go play Perl golf... Lourens -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: PeteK on 14 Nov 2006 19:08 Yechezkel Mett wrote: > James Kanze wrote: >> Except that C++ isn't English. Otherwise, a pointer to int >> would be declared "*int p;". And const(ant) pointer to int >> "const *int p;". The whole point of the argument is that in >> most cases, you don't have a choice; the modifier must come >> after what it modifies. So there is a strong argument to be >> coherent. > > There I disagree. In "int*" int is the modifier; what we have here is a > kind of pointer, not a kind of int. Of course, the "int *const" argument > is still there - const must follow what it modifies in this case. > However, given the inherent inconsistencies, I prefer to put the const > closest to what it modifies and furthest from what it doesn't modify, > thus "const int*" and "int *const", making it obvious what is const in > each case. > This is where almost everyone appears to get it wrong. The * doesn't belong to the type, it belongs to the variable (so I suppose I'm sort of agreeing with Yechezkel). Consider the following: int a = 1, b = 2, c = 3; If * belongs to the type then we could legitimately write pointer declarations as: int * x = &a, y = &b, z = &c; But of course only x is a pointer, y & z are ints. You have to write: int *x = &a, *y = &b, *z = &c; Now if you write: const int *x = &a, *y = &b, *z = &c; it becomes obvious to what the const refers. Of course you still have the nasty postioning of the const qualifier for the pointer, but that can't be helped. I'd much prefer an algol-like syntax: int i; * int pi; * const int pci; const * int cpi; const * const int cpci; but that ain't going to happen. PeteK -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: James Kanze on 14 Nov 2006 20:46 Lourens Veen wrote: > James Kanze wrote: >> Lourens Veen wrote: >>> I'm not sure if I'm a beginner, but I don't see why this should be >>> surprising: >>> const A a; // can't change a >>> const B b; // can't change b >>> const PtrInt pi1; // can't change pi1 >> Because that's not the way it works in general: >> const int* pi ; // can't change pi ?? > For pointers, but only for pointers. For everything else it does work > that way, including built-in types, class types and typedef'ed > pointers. Only for everything that cannot be specified in the declaration specification. In fact, all derived types (although pointers and functions are the most frequent cases, since arrays can't be declared const). I don't quite see your point: you say that's the way it works in general, but in fact, that's only the way it works in one specific case, where there is nothing but the object name in the declarator. The general rule is that the const modifies what is to the left of it, except in cases where order doesn't matter. >> Note that C++ declaration syntax is not easy, and putting the >> const behind, rather than before, doesn't magically make it so. >> I find it better, but the difference isn't necessarily enormous. >> No matter where you put the const, unless the reader knows how >> the declaration syntax really works, there will be cases where >> it is less than obvious. > Indeed. In another post, I suggested changing, or perhaps rather > augmenting, pointer syntax to something like > const ptr<int> x; > ptr<const int> y; > That would make pointer declarations similar to everything else. Similar to arrays? Similar to functions? Regretfully, the syntax is completely broken, and no simple fix is sufficient. > Function pointers could be > function_ptr<void, int, int> f; > for a pointer to a function returning a void and taking two ints. With > variadic templates and template typedefs, this could even be defined > within the language itself. > I would prefer that over the current > void (*f)(int, int); > which I had to look up to find that my initial guess was way off. And you haven't yet had to deal with a function that returned a reference to an array:-). > Granted, I'm sure I would have got it right if I used function > pointers regularly, but I still think the above syntax would be a lot > less cryptic. Sure, it's a bit more verbose than the asterisk, but if > I want to avoid wearing down my keyboard I'll go play Perl golf... Well, at least we agree on one thing:-). Having dealt with some fairly complicated declarations in my day, I don't think there is a simple fix. What we really need is declarations which 1) are guaranteed to begin with a key word, so there is no ambiguity as to what is a declaration and what is an expression statement, and 2) declarations which read in a normal English order. Something like: variable i: int ; variable p: pointer to int ; variable a: array[ 5 ] of int ; // ... function f( i: in int, d: in double ) : int ; procedure p( i: in int, d: out double ) ; // ... Of course, such a change would break all existing code. (But after such a change, it would make perfect sense for const to precede what it modified.) -- James Kanze (Gabi Software) email: james.kanze(a)gmail.com Conseils en informatique orient?e objet/ Beratung in objektorientierter Datenverarbeitung 9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34 -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Lourens Veen on 15 Nov 2006 11:41
James Kanze wrote: > Lourens Veen wrote: >> James Kanze wrote: >>> Lourens Veen wrote: >>> Because that's not the way it works in general: > >>> const int* pi ; // can't change pi ?? > >> For pointers, but only for pointers. For everything else it does >> work that way, including built-in types, class types and typedef'ed >> pointers. > > Only for everything that cannot be specified in the declaration > specification. In fact, all derived types (although pointers > and functions are the most frequent cases, since arrays can't be > declared const). Okay, I see where you're coming from now. It does work for templates however, which are also in a sense derived types, and I use templates much more often than bare pointers and arrays. What I'm trying to do is recast pointer and reference declarations in a template mold. Function declarations are another kettle of fish altogether, since you can't pass functions by value; there are only function pointers. Personally I don't find function declarations to be particularly complex; it's the function pointer declarations that get me. The lambda proposal (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1958.pdf) would allow new kinds of function declarations, but I'm not sure whether that makes things better or worse. It's been a while since I've done any functional programming, but the higher-order function declaration on page 10 seems a lot more complex than I remember higher-order function declarations in functional languages. >>> Note that C++ declaration syntax is not easy, and putting the >>> const behind, rather than before, doesn't magically make it so. >>> I find it better, but the difference isn't necessarily enormous. >>> No matter where you put the const, unless the reader knows how >>> the declaration syntax really works, there will be cases where >>> it is less than obvious. > >> Indeed. In another post, I suggested changing, or perhaps rather >> augmenting, pointer syntax to something like > >> const ptr<int> x; >> ptr<const int> y; > >> That would make pointer declarations similar to everything else. > > Similar to arrays? Similar to functions? I seem to recall arguments in this group for std::vector<X> array1; as the proper syntax for arrays in C++ on more than one occasion :-). That extends to const std::vector<X> array2; std::vector<const X> array3; const std::vector<const X> array4; quite nicely. And if you do need a bare array, what's the problem with declaring it as std::array<X, 42> array5; > Regretfully, the syntax is completely broken, and no simple fix > is sufficient. I'd like to see how far we can get using template-style declarations for pointers and references, including function pointers; they're already part of the language, and none of the things I've suggested here breaks existing code (except where it introduces new keywords). >> Function pointers could be > >> function_ptr<void, int, int> f; > >> for a pointer to a function returning a void and taking two ints. >> With variadic templates and template typedefs, this could even be >> defined within the language itself. > >> I would prefer that over the current > >> void (*f)(int, int); > >> which I had to look up to find that my initial guess was way off. > > And you haven't yet had to deal with a function that returned a > reference to an array:-). function_ptr<std::array<int> &, int, int> f; Easy as pie. At least this way. Lourens -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |