Boost logo

Boost :

Subject: Re: [boost] [contract] move operations and class invariants
From: Julien Blanc (julien.blanc_at_[hidden])
Date: 2017-11-29 07:04:01


Le 2017-11-29 05:39, Lorenzo Caminiti via Boost a écrit :
> Hello all,
>
> This is not really a question about Boost.Contract, but more a
> question on how contract programming interacts with C++ move
> operations.
>
> C++ requires that moved-from objects can still be destructed. Because
> contract programming requires class invariants to hold at destructor
> entry, it follows that moved-from objects must still satisfy class
> invariants.

This is not only about destructors, but more generally about reusing
moved-from objects.

> That sounds restrictive... and it might force the class invariants to
> be empty. For example, for vector a class invariant is size() <=
> capacity(). Should that sill hold after the vector has been moved?
> That means I can still call size() and capacity() on a moved-from
> object, which might not be the case.

If it can’t hold, that should be part of the contract. IMHO moving-from
can result in two situations :
1) reverting back to an empty state
2) going to an invalid state

The bad thing with 2) is that currently you have no way to compile-time
check it, and it will lead to crashes. 1) is safer, but has problems
with RAII, since the object no longer hold any resource.

> If some sort of moved() function could be called on a moved-from
> object, the invariants could be programmed as follow to work around
> this issue:

> I'm not really sure... What do you think? Do you know if this topic
> "C++ move & class invariants" has already been discussed somewhere?

I’m not aware of any litterature on this.

At first glance, i’ll separate two things :

- value types (such as std::vector), for which move semantic is mainly a
performance matter. For those types, 1) (empty state) makes a lot of
sense.
- entity types (which holds resource), for which move semantic is really
an ownership transfer. For those types, 1) doesn’t make a lot of sense,
and 2) may lead to hard to debug crashes. In the current state of the
language, I’d rather make these types not movable, and use unique_ptr to
transfer ownership.

Regards,

Julien


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk