Proposal - Revised Syntax for const and final
Reiner Pope
some at address.com
Sat Sep 8 21:04:11 PDT 2007
Reiner Pope wrote:
> Janice Caron wrote:
>> The fact that
>> const(int**) s;
>> const(int*)* s;
>> both mean the same thing is highly counterintuitive.
>
> I agree. However, I think this problem can be solved with much smaller
> changes.
>
> The syntax would be consistent if const(T) was a type constructor which
> gave a type like T, but with tail const. Consider the struct A, defined
> below:
>
> struct A
> {
> int x;
> }
>
> The types const(A) and A should behave identically, as there is no
> "tail" to be made constant. The following code is valid:
>
> const(A) a;
> a.x = 5; // nothing wrong here
>
> Now consider the array type constructor, [], which takes a type T and
> returns the array type T[]. For this to be a sensible type constructor,
> any operation permitted on T should be permitted on the elements of T[].
> This is true of user-land type constructors (templated structs, etc)
> but not of pointers and arrays. Consider:
>
> struct MyArray(T)
> {
> T firstElem;
> }
>
> This is a valid type constructor, which takes a type T and returns an
> array of T (admittedly, the array isn't very interesting -- it only has
> one element -- but you can still call it an array). Now contrast the use:
>
> const(A)[] b;
> b[0].x = 5; // error, b[0].x is not mutable
>
> MyArray!(const(A)) c;
> c.firstElem.x = 5; // fine
>
>
> Now you might complain and point out that const(A)[] actually contains A
> behind a pointer, whereas MyArray!(const(A)) stores A directly. Well, we
> solve that problem by instead declaring MyArray as a class:
>
> class MyArray2(T)
> {
> T firstElem;
> }
>
> MyArray2!(const(A)) c2;
> c2.firstElem.x = 5; // still fine
>
> [Note that I'm showing the reference behaviour with classes and not with
> pointers because both pointers and arrays have this "taint" that I'm
> trying to show is inconsistent.]
>
>
> This is a very inconsistent behaviour. We used to have the property that
> any member accessible of an instance of T is also accessible of an
> element of T[]. This is no longer true, and it means that generic code
> may require extra special cases.
>
>
> The way to fix it is simply to remove the special cases, which exist for
>
> const(T)*
>
> and
>
> const(T)[]
>
> In both of these cases, the data pointed to should be tail const.
> Currently, it is head *and* tail const.
>
>
>
> -- Reiner
I think I was a bit round-a-bout with that. Here's a simpler argument:
for any type T, T* should mean "pointer to T". If you have
struct A
{
int x;
int* y;
}
then consider const(A)*. From the above definition, this should mean
"pointer to const(A)", or in other words, "pointer to tail-const A". Yet
experimentation clearly shows that const(A)* is not "pointer to
tail-const A", but is actually "pointer to head- and tail-const A":
const(A)* b;
(*b).x = 5; // not allowed, but should be
*(*b).y = 6; // shouldn't be allowed, and isn't
-- Reiner
More information about the Digitalmars-d
mailing list