Sorry, looks like we crossed in flight.

On Tue, 31 May 2022 at 10:06, Sébastien Bini <sebastien.bini@gmail.com> wrote:
> But you need std::relocate, AFAIK, in order to implement an "emplace_back-by-relocating" operation.

What is proposed is:
std::vector<T, Alloc>::push_back(std::relocate_t, T value)
{
    /* relocate value using std::relocate_at at the end of the vector */
}
std::relocate_t being a tag type to distinguish between other push_back overloads. It is then called like that:

std::vector<T> vec;
T obj;
vec.push_back(std::relocate, reloc obj); // with inline constexpr std::relocate_t std::relocate{};

That way the object is relocated into the function parameter and then from the function parameter to the vector. There may be ways to alleviate that extra relocation.

It is on one hand clearer to write, and on the other hand has the advantage of allowing you to relocate local variables.

I don't see the need for push_back to take a tag parameter at all; we can just add push_back by value: void push_back(T value);. Possibly the overload resolution rules will need updating, or the existing overloads (T&& / T const&) could be removed.

> q1 has no "move assignment operator", remember?  We're postulating that gsl::non_null<int*> is one of these types that lacks a moved-from state. So it certainly cannot have a move assignment operator nor a move constructor.

Yes, I am telling you the rules as of today. The focus wasn't put on reloc assignment as you pointed out. I do believe there is less need to "reloc-assign" than to "reloc-construct", as they solve different problems.

"reloc-assign" is just assignment by value: operator=(T).  See my email just now.