Invariant doesn't apply to declared symbols

Janice Caron caron800 at googlemail.com
Fri Nov 30 07:56:25 PST 2007


On Nov 30, 2007 12:43 PM, Janice Caron <caron800 at googlemail.com> wrote:
> > So here's my latest and greatest idea. What about:

Scrap that last idea. I thought of a better one...

I started thinking ahead, to the time, however far off it is in the
future, when D has C++-style references, and I started to think about
what the syntax would be, in relation to const etc.

The thing about references is, unlike pointers, they don't chain. You
can chain pointers indefinitely - you can have a pointer to a pointer
to a pointer to... ad infinitum, and each new level of indirection
creates a new type. But it doesn't work like that with references. A
reference to a reference is just a reference. T& is the same type as
T&&, which is the same type as T&&&&&&&&&&&&&&&&&&&, and so on.

It's all pretty simple and straightforward really. For any
non-reference type T, T& is a new type: a reference-to-T. But for any
reference type T, T& is the same thing as T. The rest follows
logically.

Now let's think ahead, and /imagine/ that we have C++-style references
in D. Then...

    int x; // x is an int
    int* x; // x is a pointer to int
    int& x; // x is a reference to int

And with const thrown in...

    const(int)* x; // x is a pointer to const int
    const(int)& x; // x is a reference to const int

And then it occurred to me that this notation completely solves the
problem of how to make existing reference types (e.g. classes) const.
It is obvious that

    class C
    {
        int x;
    }

    const(C)& // c is a mutable reference to a const C
    const(C&) // c is a const reference to a const C

but the cool bit is the final step. Since C& is the same thing as C
(because C is a reference type), it follows that we can simplify the
second one to

    const(C) // c is a const reference to a const C

...which of course, is the existing syntax, albeit with a different
(and more obvious) meaning. So "C" is the same thing as "C&", and
"const(C)" is the same thing as "const(C&)".

What this means is that we now have a simple, and future-extendable
syntax for distinguishing between const references and const data.

    const(C) c = new C;
    const(C)& d = new C;

    c = new C; // Error
    d = new C; // OK
    d.x = 100; // Error

The syntax is "future-proof", in that, one day, we might get C++
references, and if and when we do, this syntax will cover it.

    struct S
    {
        int x;
    }

    const(S&) s;
    const(S)& t;

    s = new S; // Error;
    t = new S; // OK;
    t.x = 100; // Error;

Observe that because a struct is not a reference type, S is a
different type from S&. However, S&& is exactly the same type as S&.
That's just the way that references work.

I'm not pushing for references in D. I hope they'll come one day, but
it's not a priority for me. The point of this post is that this
/syntax/ for constness-of-classes would be consistent with future
expansion.

Compare this with the current syntax, which is:

    const(C) c; /* c is a reference to const C */
    const(int) n; /* n is a mutable int */

    const C c; /* c is a const reference to const C */
    const int n; /* n is a const int */

It seems clear to me that the proposed new syntax would be better

    const(C) c; /* c is a const reference to const C */
    const(C)& c; /* c is a mutable reference to const C */
    const(int) n; /* n is a const int */

    const C c; /* same as const(C) c; */
    const int n; /* same as const(int) n; */



More information about the Digitalmars-d mailing list