Let\'s say I got a Foo class containing an std::vector constructed from std::unique_ptr objects of another class, Bar.
Confusing as it might seem, an rvalue-reference binds to an rvalue, but used as an expression is an lvalue.
Basically, every object which has a name is an lvalue. When you pass an object to a function using an rvalue reference the function actually sees an lvalue: it is named. What the rvalue reference does, however, indicate is that it came from an object which is ready to be transferred.
Put differently, rvalue references are assymmetrical:
std::move(o))bar is defined as an rvalue-reference, but its value-category is an lvalue. This is so because the object has a name. If it has a name, it's an lvalue. Therefore an explicit std::move is necessary because the intention is to get rid of the name and return an xvalue (eXpiring-rvalue).
bar is actually an lvalue, so you need to pass it through std::move, so that it is seen as an rvalue in the call to push_back.
The Foo::AddBar(UniqueBar&& bar) overload simply ensures that this overload is picked when an rvalue is passed in a call to Foo::AddBar. But the bar argument itself has a name and is an lvalue.