C++ Logo


Advanced search

Re: [std-proposals] Relocation in C++

From: Marcin Jaczewski <marcinjaczewski86_at_[hidden]>
Date: Mon, 2 May 2022 14:41:37 +0200
pon., 2 maj 2022 o 13:30 Giuseppe D'Angelo via Std-Proposals
<std-proposals_at_[hidden]> napisał(a):
> Hello!
> On 02/05/2022 12:23, S├ębastien Bini wrote:
> > Hello Giuseppe,
> >
> > Thank you for your feedback.
> >
> >
> > > Anyways, a justification for relocation over move semantics on page 3
> > > says that "the move constructor performs extra operations to ensure that
> > > the moved-from object remains at a valid state." This is not universally
> > > true. It is true for the Standard Library (and makes certain std::list
> > > implementations of move operations expensive / noexcept(false)); that's
> > > just stdlib's stance.
> >
> > Indeed it is not universally true. The phrasing may be too general, but
> > there are indeed cases where the move constructor is:
> > - either not trivial to implement, because of that moved-from instance
> > that must remain valid
> It does not need to remain valid. A moved-from instance can be merely be
> partially-formed.
> > - either performs extra costly operations that could be avoided, had we
> > known that the moved-object will not be reused.
> But do you have concrete examples where the benefits would be
> significant? std::list is a case of the stdlib shooting itself in the foot.
> >
> > > A class author can always state that a moved-from
> > > object of their class is only partially formed. In this last case, I am
> > > not sure the paper convincly justifies operator reloc over the status
> > > quo (which includes clang-tidy "use after move" checks and so on).
> >
> > Stating that the moved-from object is invalid and should not be touched
> > again is (in my opinion) a bad class design. You may have a look at
> > https://herbsutter.com/2020/02/17/move-simply/
> > <https://herbsutter.com/2020/02/17/move-simply/>, which further
> > motivated me to write this paper. Quoting Herb Sutter: "In C++, an
> > object is valid (meets its invariants) for its entire lifetime, which is
> > from the end of its construction to the start of its destruction (see
> > [basic.life]/4). Moving from an object does not end its lifetime, only
> > destruction does, so moving from an object does not make it invalid or
> > not obey its invariants." Relocation allows to make an object invalid
> > before it is destructed, albeit it is never touched again except by its
> > destructor.
> I (and many others) profoundly disagree with that blog post's
> conclusion. Please review P2027, P2345 and the excellent talk by Marc
> Mutz at MeetingC++. The bottom line is that moved-from objects do not
> need to be valid, but only partially-formed.
> Clearly you are free to disagree with the partially-moved stance, but
> then there needs to be profound motivation in the paper regarding why
> relocation is more beneficial than designing classes according to that
> criterion.

I think a hybrid approach should be done:
a) All standard types are valid after move
b) Standard only assumes that user type is partially-formed after move.

This means if users do not need narrow contract types, they are not
forced by standard to use them.
But if there is need for types like this, standard do not hinder users
with not needed requirements.

I think even there should be a type trait that could inform the user
that a given type has a wide or narrow contract after a move.
Probably it can't be compiler provided but class creator could
specialize it to signal others how this type should be used.

This is important as generic libraries would like to have a wide
contract even if the user given type does not have it.
With this trait it easy to "fix" given type:

if constexpr (std::invalid_after_move_v<T>) t = {};

or if can't work in some contexts:

require std::valid_after_move_v<T>

Received on 2022-05-02 12:41:49