2

I am having issues debugging an std::vector<std::unique_ptr<>> with an abstract class error. The error from what I can tell is trying to using vector.push_back() on a std::unique_ptr.

Components.h

namespace cr {
    class Component {
    public:
        Component();
        virtual ~Component();
        virtual void draw() = 0;
        virtual void inflate(Frame frame) = 0;
    private:
        Frame _frame;
    };

    class ButtonComponent : public Component {
    public:
        void draw();
        void inflate(Frame frame);
    };
}

Components.cpp

void cr::ButtonComponent::draw()
{
}

void cr::ButtonComponent::inflate(cr::Frame frame)
{
}

cr::Component::Component()
{
}

cr::Component::~Component()
{
}

Window.h part of window

class View {
        friend class ViewController;
    public:
        void render();
        void insert(std::unique_ptr<Component> component);
    protected:
        void inflate();
    private:
        Frame frame;
        std::vector<std::unique_ptr<Component>> _components;
    };

Window.cpp part of window

void cr::View::render()
{
    for (auto& c : _components) {
        c->draw();
    }
}

void cr::View::insert(std::unique_ptr<Component> component)
{
    _components.push_back(component);
}

void cr::View::inflate() {
    for (auto& c : _components) {
        c->inflate(frame);
    }
}

Error output

1>------ Build started: Project: test, Configuration: Debug Win32 ------
1>  RWindow.cpp
1>c:\program files (x86)\microsoft visual studio 14.0\vc\include\xmemory0(737): error C2280: 'std::unique_ptr<cr::Component,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function
1>          with
1>          [
1>              _Ty=cr::Component
1>          ]
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\memory(1435): note: see declaration of 'std::unique_ptr<cr::Component,std::default_delete<_Ty>>::unique_ptr'
1>          with
1>          [
1>              _Ty=cr::Component
1>          ]
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\xmemory0(857): note: see reference to function template instantiation 'void std::allocator<_Ty>::construct<_Objty,std::unique_ptr<cr::Component,std::default_delete<cr::Component>>&>(_Objty *,std::unique_ptr<cr::Component,std::default_delete<cr::Component>> &)' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<cr::Component,std::default_delete<cr::Component>>,
1>              _Objty=std::unique_ptr<cr::Component,std::default_delete<cr::Component>>
1>          ]
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\xmemory0(857): note: see reference to function template instantiation 'void std::allocator<_Ty>::construct<_Objty,std::unique_ptr<cr::Component,std::default_delete<cr::Component>>&>(_Objty *,std::unique_ptr<cr::Component,std::default_delete<cr::Component>> &)' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<cr::Component,std::default_delete<cr::Component>>,
1>              _Objty=std::unique_ptr<cr::Component,std::default_delete<cr::Component>>
1>          ]
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\xmemory0(996): note: see reference to function template instantiation 'void std::allocator_traits<_Alloc>::construct<_Ty,std::unique_ptr<cr::Component,std::default_delete<cr::Component>>&>(std::allocator<_Ty> &,_Objty *,std::unique_ptr<cr::Component,std::default_delete<cr::Component>> &)' being compiled
1>          with
1>          [
1>              _Alloc=std::allocator<std::unique_ptr<cr::Component,std::default_delete<cr::Component>>>,
1>              _Ty=std::unique_ptr<cr::Component,std::default_delete<cr::Component>>,
1>              _Objty=std::unique_ptr<cr::Component,std::default_delete<cr::Component>>
1>          ]
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\xmemory0(995): note: see reference to function template instantiation 'void std::allocator_traits<_Alloc>::construct<_Ty,std::unique_ptr<cr::Component,std::default_delete<cr::Component>>&>(std::allocator<_Ty> &,_Objty *,std::unique_ptr<cr::Component,std::default_delete<cr::Component>> &)' being compiled
1>          with
1>          [
1>              _Alloc=std::allocator<std::unique_ptr<cr::Component,std::default_delete<cr::Component>>>,
1>              _Ty=std::unique_ptr<cr::Component,std::default_delete<cr::Component>>,
1>              _Objty=std::unique_ptr<cr::Component,std::default_delete<cr::Component>>
1>          ]
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\vector(1284): note: see reference to function template instantiation 'void std::_Wrap_alloc<std::allocator<_Ty>>::construct<_Ty,std::unique_ptr<cr::Component,std::default_delete<cr::Component>>&>(_Ty *,std::unique_ptr<cr::Component,std::default_delete<cr::Component>> &)' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<cr::Component,std::default_delete<cr::Component>>
1>          ]
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\vector(1283): note: see reference to function template instantiation 'void std::_Wrap_alloc<std::allocator<_Ty>>::construct<_Ty,std::unique_ptr<cr::Component,std::default_delete<cr::Component>>&>(_Ty *,std::unique_ptr<cr::Component,std::default_delete<cr::Component>> &)' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<cr::Component,std::default_delete<cr::Component>>
1>          ]
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\vector(1276): note: while compiling class template member function 'void std::vector<std::unique_ptr<cr::Component,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>::push_back(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)'
1>          with
1>          [
1>              _Ty=cr::Component
1>          ]
1>  c:\users\matt\documents\game development\projects\crengine\test\rwindow.cpp(14): note: see reference to function template instantiation 'void std::vector<std::unique_ptr<cr::Component,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>::push_back(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' being compiled
1>          with
1>          [
1>              _Ty=cr::Component
1>          ]
1>  c:\users\matt\documents\game development\projects\crengine\test\rwindow.h(19): note: see reference to class template instantiation 'std::vector<std::unique_ptr<cr::Component,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>' being compiled
1>          with
1>          [
1>              _Ty=cr::Component
1>          ]
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Background on Project

A simple GUI which has a window, a view controller which holds multiple views. The views hold multiple components (also known as widgets). SFML and OpenGL are used during the project.

Matthew
  • 682
  • 1
  • 10
  • 30
  • 1
    `std::unique_ptr` is non-copyable, see [this link](http://stackoverflow.com/questions/3283778/why-can-i-not-push-back-a-unique-ptr-into-a-vector). Try passing the `unique_ptr` by reference in your insert function and try `push_back(std::move(component))` – tforgione Feb 14 '17 at 16:16
  • thumbs up for posting the full error message. Unfortunately the double scrollbars make it almost impossible to read it. You could for example remove the paths – 463035818_is_not_a_number Feb 14 '17 at 16:17
  • @tobi303 thanks for the input. I added more then I needed to because the last couple of question I have had there were complaints that I did not include enough stuff. – Matthew Feb 14 '17 at 17:27

1 Answers1

5

Next time please simplify the code to just the relevant parts, where the error message comes from. The rest is just noise.

#include <memory>
#include <vector>

int main()
{
  std::vector<std::unique_ptr<int>> v;
  std::unique_ptr<int> p;
  v.push_back(p);
}

This tries to insert a copy of p into the vector, which is not allowed because you can't copy a unique_ptr (it's unique).

You need to move it instead of copying it, so that ownership transfers from p to the new element in the vector:

  v.push_back(std::move(p));
Jonathan Wakely
  • 153,269
  • 21
  • 303
  • 482
  • To be fair, he may have thought that it was the ABC that was the problem, but even then, `struct ABC{ virtual ~ABC() = 0; }; struct S : ABC{ ~S() {} };` and `std::vector> v; std::unique_ptr p(new S);` would have been a lot better. – Martin Bonner supports Monica Feb 14 '17 at 16:42
  • Either way, reducing it to the smallest example that still fails would help narrow down what the real problem is, and might have helped him debug it by himself. – Jonathan Wakely Feb 14 '17 at 16:47