error with vector, unique_ptr, and push_back
Asked Answered
S

1

5

I am learning smart pointers, with the following example test.cpp

#include<iostream>
#include<vector>
#include<memory>

struct abstractShape
{
    virtual void Print() const=0;
};

struct Square: public abstractShape
{
    void Print() const override{
        std::cout<<"Square\n";
    }
};

int main(){
    std::vector<std::unique_ptr<abstractShape>> shapes;
    shapes.push_back(new Square);

    return 0;
}

The above code has a compilation error "c++ -std=c++11 test.cpp":

smart_pointers_2.cpp:19:12: error: no matching member function for call to 'push_back'
    shapes.push_back(new Square);

Could someone help explain the error to me? By the way, when I change push_back to emplace_back, the compiler only gives a warning.

Steffie answered 2/4, 2022 at 9:36 Comment(0)
I
7

push_back expects an std::unique_ptr, when passing raw pointer like new Square, which is considered as copy-initialization, the raw pointer needs to be converted to std::unique_ptr implicitly. The implicit conversion fails because std::unique_ptr's conversion constructor from raw pointer is marked as explicit.

emplace_back works because it forwards arguments to the constructor of std::unique_ptr and construct element in direct-initialization form, which considers explicit conversion constructors.

The arguments args... are forwarded to the constructor as std::forward<Args>(args)....

Intersect answered 2/4, 2022 at 9:39 Comment(2)
Thanks! How could I get rid of the warning emplace_back? I also tried shapes.emplace_back(std::make_unique<Square>());, and used c++14Steffie
@Steffie you need a virtual-dtor in abstractShape, even if it is default. Add virtual ~abstractShape() = default; to that class. That should also allow C++14 make_unique semantics to wire up correctly as well. See it live.Dapper

© 2022 - 2024 — McMap. All rights reserved.