| |
 | Posted by Steven Schveighoffer in reply to Stewart Gordon | Permalink Reply |
|
Steven Schveighoffer 
Posted in reply to Stewart Gordon
| On Fri, 27 Jan 2012 08:05:24 -0500, Stewart Gordon <smjg_1998@yahoo.com> wrote:
> On 26/01/2012 15:27, Steven Schveighoffer wrote:
> <snip>
>> auto tsm = TestStruct(&xm);
>> auto tsc = TestStruct(&xc);
>> auto tsi = TestStruct(&xi);
>>
>> writeln(typeof(tsm).stringof); // TestStruct
>> writeln(typeof(tsc).stringof); // const(TestStruct)
>> writeln(typeof(tsi).stringof); // immutable(TestStruct)
>
> To actually get an immutable object (trying it on DMD 2.057), you need to use
>
> auto tsi = immutable(TestStruct)(&xi);
Right, the above is a proposed behavior for inout constructors. The point is that an inout constructor could be useful for replacing three constructors, each of which would have to be marked const, immutable, or mutable (no marks).
> I think the reason is: Think of a constructor as a method that always returns this. The implicit this pointer points to a space that has been allocated in advance to hold the constructed object.
>
> this(inout(int)* d) inout {
> this.data = d;
> }
>
> auto ts = TestStruct(&xi);
>
> is essentially
>
> inout(TestStruct) ctor(inout(int)* d) inout {
> this.data = d;
> return this;
> }
>
> TestStruct temp;
> auto ts = temp.ctor(&xi);
This is not true. A constructor used on an initializer is special in that the constructed struct does not logically exist before the construction. This may be the way it currently works in the compiler, but that is a bug.
Essentially, this:
this(inout(int)* d) inout { this.data = d; }
should reduce to this:
this( int * d) {this.data = d;}
this( const(int)* d) const {this.data = d;}
this(immutable(int)* d) immutable {this.data = d;}
Which already works today (the three constructors I mean).
> The implicit this pointer is a TestStruct* (mutable), but &xi is an immutable(int*). The only way to match both is to match the inout as const, so a const is what it returns.
No, the implicit this pointer's constancy is decided by the attribute on the constructor. In the case of constructors, the const or immutable attribute becomes the attribute of the return value. Inside the constructor, special rules are used. For example, you can assign to member variables once, even in a const or immutable ctor.
> But it doesn't work properly with a class instead of a struct at the moment.
I just tested, and it actually compiles for a struct, but doesn't work properly. Instead I get const for both immutable and const.
>> I'll note that I don't think this is currently supported, but I could see how it would be
>> useful.
>
> You away from your usual testing station?
No, just busy (and a little lazy) :) I tested it now, and I see it doesn't do the proper thing.
>> However, in that bug report, there are no inout parameters besides the 'this' pointer, so
>> I'm not sure what the purpose would be there.
>
> The purpose of it in the example is to be a minimal testcase for the bug.
>
> But in the general case, the purpose is to enable a mutable, const or immutable object to be constructed to wrap existing data that has the same constancy.
Yes, I agree. But you need to put inout on the parameter in order for it to properly reach the result (the constructed object)
I suspect the special case of the ctor is not treated correctly.
I'll file a bug.
-Steve
|