tail const

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Sat Dec 4 08:06:14 PST 2010


On 12/4/10 9:58 AM, Michel Fortin wrote:
> On 2010-12-04 08:55:19 -0500, Andrei Alexandrescu
> <SeeWebsiteForEmail at erdani.org> said:
>
>> If conversion is allowed only for values (i.e. perform a memberwise
>> copy of one struct to another), it looks like things could work.
>> Almost. The problem is that that surreptitious copy completely
>> bypasses the constructor:
>>
>> struct A(T) {
>> private T obj;
>> private bool isObject;
>> this(T obj_) {
>> obj = obj_;
>> static if (is(T == Object)) isObject = true;
>> }
>> }
>>
>> auto a = A!Widget(new Widget);
>> A!Object b = a; // works, new automatic conversion rule
>> assert(!b.isObject); // passes, invariant is messed up
>
> Copying a struct always bypasses the constructor, whether it's a
> template or not.

That's not copying, it's moving, and it always preserves type.

> If you want to maintain invariants, add the
> "this(this)" postblit constructor.

The postblit constructor assumes the source and target types are the same.

> Your invariant in the case above is a
> little silly since it stores a value deduced from the template parameter
> as a member variable. But if it's that important, fixing it is trivial:
> add a postblit constructor.
>
> this(this) {
> static if (is(T == Object)) isObject = true;
> else isObject = false;
> }

The problem is the default and implicit behavior is broken.

> I'm not sure why you imply it won't work for references. That's the
> whole point of the proposal. It can work for references as long as the
> memory layout is the same and each member can also be converted as a
> reference.

No. For references to work with mutable objects, you need equivariance, 
not contravariance. It's a classic.


Andrei


More information about the Digitalmars-d mailing list