user2946316
user2946316

Reputation:

c++ unique_ptr inside vector with inheritance

I'm playing around with the different smart pointers and ran into a problem.

I have a Environment abstract class and a ground class which inherits Environment:

class Ground : public Environment
{
protected:
    std::string type;
    int damage;

public:
    Ground() : Environment()
    {
        this->type = "ground";
    }

    virtual void SetDamage(int _damage)
    {
        this->damage = _damage*5;
    }

    virtual std::string& GetType()
    {
        return this->type;
    }

    virtual int GetDamage()
    {
        return this->damage-10;
    }

    virtual ~Ground(){}
};

I also have a Dirt class which inherits the Ground class:

class Dirt : public Ground
{
public:
    Dirt() : Ground()
    {
        this->type = "dirt";
    }

    void SetDamage(int _damage)
    {
        this->damage = _damage*6;
    }

    int GetDamage()
    {
        return this->damage-20;
    }

    ~Dirt()
    {

    }


private:

};

Now if i want to use it inside a std::vector like this:

std::vector<std::unique_ptr<Ground>> listGround;

std::unique_ptr<Ground> ground(new Ground());
listGround.push_back(ground);

std::unique_ptr<Dirt> dirt(new Dirt());
listGround.push_back(dirt); // FAIL

for (auto i = listGround.begin(); i != listGround.end(); i++)
{
    (*i)->SetDamage(80);
    std::cout << (*i)->GetType() << " " << (*i)->GetDamage() << std::endl;
}

listGround.empty();

I get a compile error saying that there is no user-defined-conversion operator available that can perform this conversion etc etc on the line that is marked FAIL in the above code.

If I use a std::shared_ptr everything works as intended. Same goes for raw pointers.

Why am I getting this error?

error C2664: 'void std::vector<_Ty>::push_back(std::unique_ptr &&)' : cannot convert parameter 1 from 'std::unique_ptr<_Ty>' to 'std::unique_ptr<_Ty> &&' 1> with 1> [ 1>
_Ty=std::unique_ptr 1> ] 1> and 1> [ 1> _Ty=Dirt 1> ] 1> and 1> [ 1> _Ty=Ground 1> ] 1> Reason: cannot convert from 'std::unique_ptr<_Ty>' to 'std::unique_ptr<_Ty>' 1>
with 1> [ 1> _Ty=Dirt 1> ] 1>
and 1> [ 1> _Ty=Ground 1> ] 1>
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

Upvotes: 3

Views: 1084

Answers (2)

b4hand
b4hand

Reputation: 9770

std::vector::push_back requires the type passed to be copyable (or in C++11 movable) and std::unique_ptr is not copyable. That's what the error message is telling you that it is missing the corresponding conversion for moving. You can move a std::unique_ptr by using the std::move function which simply does the appropriate cast to the right r-reference type.

Upvotes: 1

MSalters
MSalters

Reputation: 179809

Create the thing in place:

listGround.emplace_back(new Dirt());

It's not a shared_ptr, yet you try to have ownership shared between dirt and listGround.back()

Upvotes: 1

Related Questions