On Thursday, 11 October 2012 at 22:05:34 UTC, Jonathan M Davis
wrote:
On Friday, October 12, 2012 01:20:44 Dmitry Olshansky wrote:
> > This sounds more like a limitation of invariants, rather > than a problem
> with .init. You make (imo) a valid point.
> > Would it be complicated for opAssign to first check > memcmp(this, > T.init), and only do entry invariant check if the comparison > fails? > > Potentially ditto on exit.

With your rule T.init is a valid state. AFAICT in Jonathan's example it
isn't.

Yeah. All that's required is that you outright skip the call to the invariant before calling opAssign. It _does_ mean special casing opAssign, but I don't see that as a problem. I don't understand why it matters whether the object is valid before it's assigned to. Presumably, you're completely replacing its state, and regardless of what you actually do in the function, it would still need to be valid afterwards. So, it seems perfectly fine to me to just skip calling the variant before calling opAssign, but Walter was against it. His comment on the bug ( http://d.puremagic.com/issues/show_bug.cgi?id=5058 ) indicated that he thought that init should always be in a valid state, but since NaN and null are invalid states, I see no reason that a struct's init value can't be an invalid state. It can be copied and passed around just fine. It just wouldn't pass its invariant if you tried to call a function on it
before assigning it a valid value.

- Jonathan M Davis

Yes, as answered, opAssign may do things to this, such as
dealocate a payload, reduce a ref counter, or who knows what.

As a matter of fact, there was a bug in emplace about that I
recently fixed.

My rational for skipping the test *ONLY* if "this == .init" is
that .init is supposed to mean not yet fully initialized. This
would make code such as:

T t = t.init; //Not yet ready for use.
                //Attempt to use will assert the invariant
...
t = T(5); //Initialize it later. Don't check invariant on entry
...
//Use t and check invariants every time.
...
t = t.init; //De-initialization, Don't check invariant on exit.
              //Future attempt for use will assert the invariant

I'd also do the same for destructor entry: The language already
states that .init SHOULD be a valid destructible state.

Reply via email to