On Sun, 22 May 2022 at 13:14, Jason McKesson via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
On Sun, May 22, 2022 at 12:46 PM Edward Catmur via Std-Proposals
<std-proposals@lists.isocpp.org> wrote:
>
> On Fri, 20 May 2022 at 18:52, Thiago Macieira <thiago@macieira.org> wrote:
>>
>> I don't think that's sufficient. The change needs to be opt-in, not opt-out.
>> Otherwise, we're going to have silent breakages because of some libraries
>> recompiled and others not.
>
>
> Uh, if a library is not recompiled, then it uses the old ABI, and if it is recompiled then either it's compiled against old source code, so uses the old ABI, or is compiled against new source code with relocation operator defined but also with the opt-out in place, so it uses the old ABI.

I think his point was that you're confusing the terms "opt-in" and "opt-out".

For a feature to be "opt-in", it must be unavailable *unless* you do a
thing that specifically makes it available to you. "Opt-out" is the
*opposite*; you have the feature *unless* you do a thing to turn it
off.

The deletion behavior of defaulted move constructors in the presence
of user-provided copy constructors is an example of "opt-in". If your
type has a user-provided copy constructor, but you don't declare a
move constructor (maybe because you wrote it in C++98/03 where those
didn't exist), then your type's move constructor will be deleted. It
cannot participate in moves. Your type doesn't have a move operation
unless you explicitly ask for one.

That seems to be what you're arguing for here, just with the wrong
terminology. You are describing "opt-in" functionality, but you *call*
it "opt-out".

There is both opt-in and opt-out under this scheme. First, a nontrivial class opts *in* to relocation (trivial or otherwise), by declaring (and possibly defaulting) a relocation operation. This opt-in is necessary since nontrivial classes cannot be assumed to be automatically relocatable (they may need self-reference fixup, etc.). Next, it opts *out* of the ABI change, by annotating the relocation operation with an attribute. This opt-out means that the class is passed into functions as if it did not declare the relocation operation, so this is compatible with previously compiled code and with code compiled to an earlier standard version with the relocation operation #if defined out. 

A function parameter of a type that has opted out of the ABI change may still be the argument of the relocation operator keyword, but this will move construct the target from the source parameter (unless the relocation operator expression is a discarded-value expression) and defer destruction of the parameter to (after) the end of the function, instead of invoking the relocation operation and not destroying the function parameter.  A function parameter of a class that opts out of ABI change but has no accessible move constructor cannot be relocated within the function.

The reason to opt in *and* opt out is that this permits relocation to be used in other situations than function argument passing, esp. containers (e.g. vector reallocate) but also relocation of automatic variables and of class subobject bases and members.

Both opt-in and opt-out propagate to derived and composing classes as necessary to maintain the Rule of Zero. ABI break (opt-in without opt-out) also propagates (a class that breaks ABI for itself is assumed responsible for breaking the ABI of derived and composing classes) but can be canceled by the derived/composing class itself opting out.