From: Lourens Veen on
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

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
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
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! ]