> You'll need a relocate_wrapper type that can be (possibly implicitly)
constructed from a callee-destroy prvalue, and that releases that value
(by relocation to a prvalue) on request. So you call either
push_back(relocate_wrapper(reloc x)), or relocate_back(reloc x).
Yes, that looks about right. The double-relocation can easily be elided, especially if we give the compiler permission to do so as a behavior-affecting optimization (i.e., above and beyond as-if).
Also, if no one sees a point of having non-default base-or-member initialisers in operator reloc member function, and that its source object is already destructed once the function body is reached, what would be wrong with this operator reloc?
struct T : B
{
M data;
/*
* operator reloc returns a new instance.
* actual relocation (base-class and data-member relocations) happen before the function body is called (as if by =default).
* The function body only serves to make some adjustments, like fixing self-references.
* 'this' pointer in reloc function body points to the newly constructed instance.
* The source object is considered destructed and is no longer usable, that's why it does not appear as a parameter.
* It is not possible to provide custom base-or-member-initializer.
*/
operator reloc()
{
data.self = *this; // fix self-references here
}
};
The problem is: what if data is const? Then it will not be possible to modify data.self in the function body. So I think you would need to be able to write:
operator reloc(T&& rhs)
: data([&] { M data = std::move(rhs.data); data.self = *this; return data; }())
{}
By providing a base-or-member-initializer for data, you indicate that rhs.data should be destroyed once that initializer completes. This scheme can handle everything short of relocate-only const self-referential data members (since it has to use move-and-destroy, not relocation proper), but those are esoteric enough to not bother supporting (the user can just drop const in that case).