Remaining const niggles #1 - Custom POD types

Janice Caron caron800 at googlemail.com
Sun Feb 17 02:20:32 PST 2008


On the whole, I'm very happy with the new const system. However, there
are one or two niggles which remain, and I feel that enough time has
passed that it's safe to start bringing them up for discussion. So
here's my number one complaint. This works:

    string s = "hello";
    char c = s[0];

Nothing unusual there, you might say. The problem is that the
following /doesn't/ work (as in, won't compile!)

    typedef char mychar;
    alias invariant(mychar)[] mystring;

    mystring s = cast(mystring)"hello";
    mychar c = s[0];

The final line won't compile. The compiler, apparently, cannot
implicitly convert an invariant(mychar) to a mychar. But why not? It
can do that for char, and mychar is just a typedef for char. Changing
mychar from a typedef to a struct wrapper doesn't fix things either.

But I believe there is a solution.

The fix is, the compiler must allow const(T) and invariant(T) both to
implicitly cast to T, if and only if T is "pod". (Plain Old Data).
This is a very simple thing to define. A type T is pod if and only if
one of the following is true:

    T is a primitive type
    T is a typedef for a pod
    T is a struct in which every member variable is pod
    T is a union in which every member variable is pod

In anticipation of criticism, let me fire the first shot against this
idea myself! The problem is that whether or not a struct is pod, may
end up depending on private member variables. That means that the user
of a struct who has only the published API to go on, might assume that
a struct is pod (because all published member variables are pod), but
be unaware that the struct has private pointers.

There are two ways to deal with this criticism. The first way is to
say "Who cares?". We should all assume that types are going to be
non-pod unless they are explicitly documented as being so. This is my
favorite answer.

The second way is to decorate struct and union declarations which are
pod, so that (a) the compiler can see at a glance whether or not the
struct is pod, and (b) the podness or not of a struct appears in its
API. The word "static" could probably be reused here to denote podness
- for example:

    struct S
    {
        int * p; /* OK - S is not pod */
    }

but

    static struct T
    {
        int * p; /* ERROR - T is pod */
    }

Under this regime, the declaration of T wouldn't even compile, forcing
the writer to remove either the member variable p, or the word
"static". Without the word static, const(T) and invariant(T) will not
implicitly cast to T.

For those who don't like the reuse of the word "static", it's not the
only possible syntax. One could invent a new keyword (e.g. "pod"), or
even a new syntax (e.g. "struct(pod)" instead of "struct", which
achieves the same thing without a new keyword.)

The point is, it's the feature that matters, not the syntax of it. The
two approaches are: (a) no decoration - let the compiler figure it
out, or (b) decoration - helps everyone, but adds slightly more
surface area to the const system.

Whichever route we go, I absolutely would like to see this one
addressed. I have a good use for that mychar type I mentioned at the
start of the post. I have already submitted the example I used as a
bug in bugzilla, so we'll see what happens, but I thought I'd open up
the discussion here, to get some feel for what we D2 users think is
the best way to fix this.



More information about the Digitalmars-d mailing list