Another point: std::relocate_at(p, q) is just new (p) T(std::relocate(q)). So if anything it's std::relocate_at that's unnecessary.

I agree with you on the confusion; since we expect non-experts to use operator reloc only, std::relocate could be given a longer, more technically oriented name.

I agree with both statements.
 
As a tiebreaker, prefer passing by value for prvalue arguments. Specifically, I would amend [over.ics.rank]/3.2.3 to read:

- neither of S1 and S2 bind a reference to an implicit object parameter of a non-static member function declared without a ref-qualifier, and either:
  - S1 binds an lvalue reference to an lvalue, and S2 does not, or:
  - S1 binds an rvalue reference to an xvalue, and S2 does not, or:
  - S1 does not bind a reference, and S2 binds a reference to a prvalue, or:
  - S1 binds an rvalue reference to a prvalue, and S2 binds an lvalue reference [Example:
int i;
int f1();
int&& f2();
...
int g2(const int&);
int g2(int);
int g2(int&&);
int j2 = g2(i); // calls g2(const int&)
int k2 = g2(f1()); // calls g2(int)
int l2 = g2(f2()); // calls g2(int&&)
...
- end example]

That sounds nice and shouldn't break existing APIs as they would today be considered as ambiguous.
 
The user can write destroy+relocate if they want; the language shouldn't be doing that.

As a user I would feel uncomfortable explicitly calling the destructor on *this to reconstruct it again.
 
This does require a bit of a conceptual leap, yes. The key is to understand that operator reloc *changes the value category* of a named object, from lvalue to prvalue. This is because relocation is the inverse operation to prvalue materialization. So by the time the relocating constructor is invoked, the argument is already a prvalue (just, uh, a prvalue that occupies storage).
 
Just to be sure I understand correctly: the reloc operator would no longer return a newly built instance (i.e. a temporary), but instead would merely transform the value category from lvalue to prvalue?
And then whether a temporary is materialized or not depends on the context, right?

Consider a type T with that putative relocation constructor T(T):

Case 1:
void foo(T a_foo);

T var;
foo(reloc var);

In `foo(reloc var);` is a_foo constructed using T(T)?

If so then `var`'s destruction is delegated to T(T), which prevents the destructor call of its parameter, right?

Case 2:
Now let's add a T& operator=(T):

T objA, objB;
objA = reloc objB;

Following the same logic as above, objB is passed to relocation constructor, and then to objA's assignment operator, right?

Case 3:
T obj;
reloc obj; // premature end-of-scope

This turns obj into a prvalue that is captured nowhere. I guess in this case the destructor of obj is simply called?

Case 4:
void bar(T&& bar_param);

T var;
bar(reloc var);

Again, reloc var turns var into a prvalue, but bar cannot capture it. So a temporary object of type T is created and its address is passed to bar, right?

If I understand correctly, then this could simplify some aspects of how operator reloc works.

However I fear many users will be lost (most C++ programmers that I know have no knowledge of value categories), and will find it quite disturbing to have a relocation constructor with that signature T(T). Sure operator reloc(T&&) may be confusing as well, but my personal take is that it would be less so :/