Now for the tricky part:
const int*
int const*
Both are equal and describe a pointer to an integer that cannot be changed. The pointer itself can be changed to point
at something else. Syntax here is already becoming more vague.
I think this is the main problem with const in C, the order of const is varying/inconsistent/different.
It becomes confusing when you usually use 'const int *', and you see 'int const *' and think it means something different. I think it would be an improvement to restrict to specific positioning.
3. Limit positioningansi-C | -> | C2 |
const int | | const int |
int const | | const int |
const int* | | const int* |
int const * | | const int* |
int* const | | int* const |
const int* const | | const int* const |
const int * const | | const int* const |
const int * const * | | const int* const * |
const int * const *const | | const int* const * const |
This positioning is what I usually see and write.
I think this would reduce confusion, and is compatible with C.
However, this is a bit inconsistent:
const int a = 4;
int * const b = &c;
The variables a and b are both constant, but in one case the const qualifier is before the type,
in the other case const is before the identifier and after the type.
To make it more consistent, you could move the first const, so the const comes after the type it qualifies.
Parentheses shouldn't be needed, think of it as a tightly binding suffix operator.
4. Const qualifier after type ansi-C | -> | C2 |
const int | | int const |
int const | | int const |
const int* | | int const * |
int const * | | int const * |
int* const | | int * const |
const int* const | | int const * const |
const int * const | | int const * const ((((int) const) *) const) // parentheses to clarify ast structure |
const int * const * | | int const * const * ((((int) const) *) const) *) // parentheses to clarify ast structure |
const int * const *const | | int const * const * const (((((int) const) *) const) *) const) // parentheses to clarify ast structure |
Now the const qualifier is consistently after the type, and is still compatible with C.
It doesn't have the usual adjective-noun order if you read it left to right, but right to left is ideal:
int const * const X = &b;
"X is a constant pointer to a constant int"
It could also be made consistent by always putting the const qualifer before the type.
This takes the * token as the position of the pointer type.
5. Const qualifier before typeansi-C | -> | C2 |
const int | | const int |
int const | | const int |
const int* | | const int * |
int const * | | const int * |
int* const | | int const * |
const int* const | | const int const * |
const int * const | | const int const * ((const (int)) (const *)) // parentheses to clarify ast structure :/ |
const int * const * | | const int const * * |
const int * const * const | | const int const * const * |
This is consistent, and it is in the usual adjective-noun order (and the [probably] more common qualifier ordering use in C).
One disadvantage with this is that It breaks compatbility with C. I realize that C compatibility is not a goal, but it does make it less confusing for C developers, who are probably the main audience.
Also, the AST structure isn't nice/clear/elegant to me.
One of the features of type qualifiers is that they can be added to an existing type, you don't need to define a new type for the qualifier. For this reason I don't like Option 2.
If you don't know the language Options 3, 4 and 5 aren't as implicitly obvious as Option 1, but they're still simple and easy to apply once known and save syntactic cluttering of parentheses.
My preference is Option 4 for being consistent, C compatible, and nice to say aloud (by saying tokens right to left).