Brian Yeh
Brian Yeh

Reputation: 3267

why does C++ give me an error when inserting unique pointer into unordered map?

in a class with the following member and method:

    std::unordered_map<std::string, std::unique_ptr<test::Test>> m_Tests;
    
    void test::TestMenu::addTest(const std::string &testName, std::unique_ptr<test::Test> test) {
        m_Tests.emplace(testName, test);
    }

called like this:

testMenu.addTest("Test Clear Color", std::make_unique<test::TestClearColor>());

The compiler delivers the error:

error: no matching function for call to 'construct_at'
          std::construct_at(__p, std::forward<_Args>(__args)...);

My question is why is C++ giving me this error?

Upvotes: 1

Views: 1793

Answers (1)

Asteroids With Wings
Asteroids With Wings

Reputation: 17464

This:

m_Tests.emplace(testName, test);

will try to copy test, because (a) it is an lvalue expression, (b) expressions never have reference type, and (c) emplace does not take an lvalue reference.

unique_ptrs cannot be copied.

This is what std::move is for!

m_Tests.emplace(testName, std::move(test));

Now you have an rvalue expression, which is perfectly suited to bind to the rvalue reference that emplace does take.

I'm actually slightly slightly lying here, and things are a bit more complicated since emplace is variadic. But whatever. The important thing is that you're creating another link in the chain of ownership for this unique_ptr, ultimately passing ownership on to the map, and std::move is the way to do that.

Upvotes: 4

Related Questions