dimanche 1 avril 2018

Why Structure Bindings disable both RVO and move?

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();

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 implictly 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.

However why can implicit move not be expected? Using explicit std::move on the return statement does not look intuitive in this particular case.

Tested by both compilers gcc and clang with -O3.

Live Demo

Aucun commentaire:

Enregistrer un commentaire