Writing const-correct code in D

Kevin Bealer Kevin_member at pathlink.com
Wed Mar 8 20:50:14 PST 2006


In article <Pine.LNX.4.64.0603081855530.30259 at bellevue.puremagic.com>, Brad
Roberts says...
>
>On Thu, 9 Mar 2006, Kevin Bealer wrote:
>
>> The same is true for struct, it gets copied in, which is fine for
>> small structs.  For larger structs, you might want to pass by "in *",
>> i.e. use "in Foo *".  You can modify this technique to use struct, for
>> that see the last item in the numbered list at the end.
>> 
>> 
>> For classes, the issue is that the pointer will not be modified with
>> the "in" convention, but the values in the class may be.
>> 
>> :   this(const_Foo b)
>> :   {
>> :     x1 = b.x1.dup;
>> :   }
>
>I must have missed something somewhere along the way.. when did copying 
>imply const?  To me, something that's const can't be modified.  That 
>doesn't mean just to the caller, but also to the callee.  It's a mechanism 
>for saying "this object shouldn't be changed".  Const by duplication 
>doesn't help with the last part and make it entirely probable that code 
>will at some point be change to modify parts of the passed in data with 
>the expectation that those changes actually occur on up through to the 
>caller.
>
>Sorry, const by dup is in some ways even worse than not having const.  I 
>see how it solves some usecases though, so it's not totally worse. :)
>
>Later,
>Brad

Yeah - this is a tradeoff, but as I understand it, the copy constructor in D
(unlike C++) can't be used for automatic conversions.  So the person receiving a
const_Foo has to do this:

: void dofoo(in const_Foo x)
: {
:    Foo y = new Foo(x); // explicit copy of value(s) from x
:    ...
: }

..in order to get a new one.  Now, normally one would not expect y to propagate
changes back to x, if the syntax looks like the above, right?

These versions won't even compile:

: void doAAA(in Foo x)
: {
:     y.modifyStuff(); // okay here
: }
:
: void doBBB(in const_Foo x)
: {
:     y.modifyStuff(); // failure here - const_Foo doesn't have this method
: }
:
: const_Foo bar;
:
: doAAA(bar); // error: can't convert const_Foo to Foo
: doBBB(bar); // okay here

So -- both are caught at *compile* time.  No .duplication unless requested
explicitely.  The clone() method and clone() constructors are designed to
do as deep of a copy as necessary, which means they need to be user defined.
That's why all the proposals for deep .dup don't work - it requires developer
input, the compiler doesn't know enough.

If you wanted to really prevent modification or copy, you can just omit that
method, and not provide a way to go from const_Foo to Foo.  I'm proposing this
as the obvious standard way to de-const -- with a constructor -- for cases where
you want that behavior.

My thinking is that we could set up rules for people who want to do const, maybe
because they have a huge C++ project they are rewriting in D, and it uses const
in complex ways.  Maybe because they just like the const facility.

Kevin






More information about the Digitalmars-d mailing list