I think Nicolai could have just phrased it a bit better.
When you return by
auto, your function returns a value (the type of which will be deduced). If
std::invoke returns a pure rvalue or an xvalue, then of course the result of
call will be constructed accordingly (by a move, if possible). We don't "lose move semantics" in that sense.
But when we return by value, that value object needs to be created. It can be created by a move, and under certain circumstances (which aren't present here) it can be elided, but it must be created. Guaranteed copy elision doesn't allow us to cop out of creating this object.
That can be quite wasteful if
std::invoke gives us back an xvalue (an rvalue reference to something). Why should we construct an object to return it?
That's why a slide or two later he says we should return by
decltype(auto). The deduction rules will then preserve the value cateogry of the the call to
If it returns a value, we are no worse off. Our own
call will return a value (which it may create by moving the return value of
std::invoke returns an lvalue(
X&) or an xvalue(
X&&), that will be returned as is, without creating another object by a copy or move.