Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why can't std::unique_ptr be returned after structured binding without using std::move?

When I try to compile the following code I get the error C2280. I guess the compiler is trying to copy the unique_ptr or something.

#include <memory>

std::pair<int, std::unique_ptr<int>> CreatePair()
{
    std::unique_ptr<int> my_int(new int);
    return { 1, std::move(my_int) };
}
std::unique_ptr<int> GetUinquePtr()
{
    auto [ignore, unique_ptr] = CreatePair();
    return unique_ptr; // <- Build error C2280 attempting to reference a deleted function
}
int main()
{
    auto unique_ptr = GetUinquePtr();
}

Complete error message:

error C2280: 'std::unique_ptr<int,std::default_delete<int>>::unique_ptr(const std::unique_ptr<int,std::default_delete<int>> &)': attempting to reference a deleted function

It works if I add std::move():

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

std::unique_ptr<int> GetUinquePtr()
{
    auto [ignore, unique_ptr] = CreatePair();
    return std::move(unique_ptr); // <- This works
}

And it works fine if I use std::tie:

std::unique_ptr<int> GetUinquePtr()
{
    std::unique_ptr<int> unique_ptr;
    std::tie(std::ignore, unique_ptr) = CreatePair();
    return unique_ptr; // <- This works
}

So do need to explicitly type std::move after structured binding of a unique_ptr or am I doing something wrong here?

>Solution :

A structured binding creates references, and your code is more or less equivalent to this:

std::unique_ptr<int> GetUinquePtr()
{
    auto p = CreatePair();
    auto& ignore = p.first;
    auto& unique_ptr = p.second;
    return unique_ptr;
}

and returning the reference would create a copy.

With the tie, it works rather like this instead:

std::unique_ptr<int> GetUinquePtr()
{
    std::unique_ptr<int> unique_ptr;
    unique_ptr = CreatePair().second;
    return unique_ptr;
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading