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.