Suppose we have a class named AAA that supports both copy/move:
class AAA
{
public:
    AAA() = default;
    ~AAA() = default;
    AAA(const AAA& rhs)
    {
       std::cout << "Copy constructor" << std::endl;
    }
    AAA(AAA&& rhs)
    {
       std::cout << "Move constructor" << std::endl;
    }
};
In the following code, get_val returns second:
AAA get_val()
{
    auto [ first, second ]  = std::make_tuple(AAA{}, AAA{});
    std::cout << "Returning - " << std::endl;
    return second;
}
auto obj = get_val();
std::cout << "Returned - " << std::endl;
Now second is copied, printing the following output:
...
Returning - 
Copy constructor 
Returned -
This is unfortunate, because my expectation of the result is either there's no call to copy constructor, or at least it's implicitly moved.
To avoid copying, I'll have to explicitly apply std::move on it.
return std::move(second);
Then I'd receive the result of:
...
Returning - 
Move constructor 
Returned - 
I assume that the reason RVO is not performed is that probably the compilers would see second as a reference instead, while get_val returns prvalue.
However why can implicit move NOT be expected either? 
Using explicit std::move on the return statement does not look intuitive in this particular case, because you generally don't want to make RVO, which is in most cases a better optimization than move, accidentally gone away.
Tested by both compilers gcc and clang with -O3. 
 
    