Transitive const sucks

Janice Caron caron800 at googlemail.com
Thu Sep 13 00:15:18 PDT 2007


On 9/13/07, Walter Bright <newshound1 at digitalmars.com> wrote:
> See Scott Meyer's article on double checked locking, for example.

Just read it. And fear not - I wouldn't make that mistake.

> > I think it could scale very well with the right language support. But
> > that's another subject.
>
> I think this is the subject <g>.

I could start another thread (...newsgroup thread, I mean...) for that.


> > programmer catch errors! For example, this C++
> >
> > class C
> > {
> >     mutable int x;
> >     int y;
> >
> >     void f() const;
> >     {
> >         x = 1;
> >         y = 2; /* The compiler catches this error */
> >      }
> > }
> >
> > See - this is useful to me. If I had not declared f const (which is
> > basically what you're suggesting), then the compiler would have been
> > no help to me whatsoever. It would not have flagged y=2 as an error.

> You can write your class as:
>
>         int x;
>         const int y;

no I can't, because then I can't add a member function g

class C
{
    mutable int x;
    int y;

    void f() const;
    {
        x = 1;
        y = 2; /* Error - f is const */
     }

    void g()
    {
        y = 3; /* OK -*/
    }
}

Much of what you said hinges on keywords being intuitive, and on that
score, I must agree with you. To me, C++'s const /means/ "logical
const", but only because I've got used to it.

If we're going to use better, more intuitive keywords, then I would
strongly argue in favor of using "readonly" to mean "a read-only view
of stuff that might be changed through some other reference", and
"const" to mean "stuff that can never be changed, ever".

The distinction between logical const and physical const *disappears
completely* if const is not transitive. That is, with non-transitive
const, one can always write a class differently such that "mutable" is
never required. Essentially, you replace

class C
{
    mutable T x;
}

with

class C
{
    T * x;
}

Then you can let x be constant, but still modify the actual variable
itself through *x.

The difficulty for me is that you want to get rid of intransitive
const, and /also/ disallow mutable.

I /like/ your syntax for applying constness to everything inside the
brackets. The notion that C++'s

int const * const * const * * * p;

can be written instead as:

const(int **)*** p;

definitely has its appeal. If you so chose, you could allow the same
functional notation to remove constness, so that

int * * * const * const * const p;

could be written in D as

const(mutable(int **)***) p;

...but if I've followed this argument correcly, you're not likely to
do that, because you believe that allowing mutable members to be
accessed through a const pointer - however indirectly - screws things
up for mulithreading. And of course, you'd be right.

...which leads me to the conclusion that - in partial agreement with
you - allowing mutable members to be accessed through a const pointer,
even indirectly, should not be allowed ... unless, and this is the
rub, *UNLESS IT CAN BE MADE THREADSAFE*

...and I believe it can. As you quite rightly point out, "mutable"
isn't enough. Even synchronised isn't enough. But I could suggest a
new language feature that /would/ be enough. I'll start a new thread
for it, once I've composed my thoughts into something approaching
documentation.

So ... you've convinced me. Now I want to convince you. The use cases
that have been listed so far justify /trying/. Your desire to make
multithreading easier also justifies trying. Hopefully there is a way
we can get the best of both worlds.



More information about the Digitalmars-d mailing list