const(X) member of Y

Dan dbdavidson at yahoo.com
Thu Feb 7 05:49:31 PST 2013


On Thursday, 7 February 2013 at 05:30:27 UTC, Maxim Fomin wrote:
> On Wednesday, 6 February 2013 at 22:54:40 UTC, Dan wrote:
>> This begs the question:
>>
>> Which of these do you choose and for what reasons:
>> - this(this){}
>
> This is natural way to define struct postblit. This fully 
> complies with current D spec. This should be used until 
> postblit constness problem is faced.
>
>> - this(this)const{}
>
> This is not normal way to define struct postblit but which 
> happens to work. Spec is silent about this. If you encounter 
> "postblit is not callable using const" message, you can 
> workaround the problem by making postblit const and forwarding 
> call to some other non-const method which actually does 
> postblitting. This is type system breakage which can be useful 
> until option 1 is fixed. Or you may use other workarounds.
>
>> - this(const this){}
>
> This is a tricky and unintuitive way to define simple struct 
> constructor which may be confused with postblit. It actually 
> means
>
> struct S { this(const S s){...} }
>
> and can be written in this way to avoid confusion.
>
>> Also, has any of this detailed information made it into the 
>> language spec?
>
> #1 is fully defined in struct chapter. #2 is not defined. #3 is 
> a particular example of omitting parameter names like void 
> foo(int) { }. D unlike C supports omitting parameter names not 
> only in function declaration, but in function definition too.
>

Immensely helpful answer, thanks!

So: Prefer #1. If you get compile error requiring postblit () 
const, take advantage of #2. Assume/hope that in the future there 
will never be a requirement to have 'this(this) const' and you 
can revert to #1 and remove the delegate trick that allowed you 
to set members in 'this(this) const'.

Regarding #2, not only does it work, in some cases it is 
required. I know of 2 cases:

struct S {
   this(this) { c=c.dup; }
   char[] c;
}
struct X {
   const(S) s;
}

So my guess is something about the "lowering" or autogenerated 
postblit of X requires the postblit to be const. I think this is 
overkill and maybe the 'const'ness of a member of S should be 
relaxed in the creation of it.

Another is the following fails to compile:

import std.stdio;
struct S {
   this(this) { c=c.dup; }
   char[] c;
}
void main() {
   const(S)[int] s1;
   const(S)[int] s2;
   writeln(s1==s2);
}

Something about opEquals is requiring the signature on S's 
this(this) to be 'this(this) const'. This really highlights two 
issues: First, the implementation of opEquals for a hash should 
*not* need to make copies of the values. There is probably an 
iteration in the implementation that should be changed to ref. 
The second is you should probably be allowed to construct a 
const(S) from another const(S) without requiring signature 
'this(this) const' in all cases.

This sort of issue comes up in the weirdest of situations.

http://dpaste.dzfl.pl/f8ddc666
This code compiles. But interestingly making the 'static if(1)' 
causes it to fail to compile. Somehow, adding a 'opEquals const' 
to T triggers the generation of a opEquals in X that requires 
S[int] to have 'opEquals const', which in turn requires S to have 
'this(this) const'.

Why so much focus on new features like properties when the 
fundamentals of const for structs are not hammered out 
sufficiently?

Thanks
Dan



More information about the Digitalmars-d mailing list