New to C and mostly enjoying the learning curve, but struggling to solve this one.
I'm needing to satisfy this requirement in two different related places
std::unique_ptr [is typically used] as the element type in move-aware containers, such as std::vector, which hold pointers to dynamically-allocated objects (e.g. if polymorphic behavior is desired)
Compilable code (toggle the "working" and "not working" to cause build/fail):
#include<vector>
#include<memory>
class Entity;
class Action
{
public:
Action() = default;
};
class World {
std::vector<std::unique_ptr<Entity> > entities;
public:
World();
};
class Entity {
public:
Entity() = default;
};
class Animal: public Entity {
protected:
// Not working - log below
std::vector<std::unique_ptr<Action> > actions;
// Working fine but doesn't support polymorphic behaviour
//std::vector<Action> actions;
public:
Animal() = default;
};
class Person: public Animal
{
protected:
World& world;
public:
Person(World& world);
};
Person::Person(World& world) : world(world)
{
}
World::World()
{
Person first = Person(*this);
entities.push_back(std::make_unique<Person>(first));
}
Which barfs the error:
/usr/include/c /9/bits/stl_uninitialized.h|307 col 37 error| required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<Action>*, std::vector<std::unique_ptr<Action> > >; _ForwardIterator = std::unique_ptr<Action>*; _Tp = std::unique_ptr<Action>]’
/usr/include/c /9/bits/stl_vector.h|555 col 31 error| required from ‘std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = std::unique_ptr<Action>; _Alloc = std::allocator<std::unique_ptr<Action> >]’
test.cpp|23 col 7 error| required from ‘typename std::_MakeUniq<_Tp>::__single_object std::make_unique(_Args&& ...) [with _Tp = Person; _Args = {Person&}; typename std::_MakeUniq<_Tp>::__single_object = std::unique_ptr<Person, std::default_delete<Person> >]’
test.cpp|48 col 54 error| required from here
/usr/include/c /9/bits/stl_uninitialized.h|127 col 72 error| static assertion failed: result type must be constructible from value type of input range
So it seems that Person first
is correctly created, but the error is coming from when make_unique<Person>(first)
is handling the unique_ptr of first.actions
. Maybe. I'm not following the process of why declaration is triggering the uninitialized_copy()
merely through lack of understanding, and though there's reams of similar questions around unique_ptr
, I find no direct references to the "nesting" thing I've got going on and 4 hours on this is about enough before resorting to asking here.
Not necessarily after a full solution, but some hints that will get me looking at the right direction would be much appreciated. Newb-level speak would be appreciated :-)
Thanks in anticipation.
Edit: Code snippet changed to be full and compilable using gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
My bad - vi coughed up the same make_unique() error as before, but compiling throws other errors - will not fix as question has been fully answered
CodePudding user response:
std::vector<std::unique_ptr<Action>>
is not copyable because std::unique_ptr<Action>
is not copyable.
std::make_unique<Person>(first)
tries to copy first
.
This can be fixed by moving (std::make_unique<Person>(std::move(first))
), but you can also forgo the intermediate local entirely:
entities.push_back(std::make_unique<Person>(*this));