unique_ptr & vector, trying to access deleted function, Visual Studio 2013

Vitali picture Vitali · Mar 31, 2014 · Viewed 23.4k times · Source

I am trying to use unique_ptr to manage my memory, and VS2013 seems to be giving me trouble when I think it shouldn't be.

It would seem that the compiler is for whatever reason trying to access a deleted copy constructor when it really should have no reason to do so.

This is what one of my classes looks like:

class Mesh
{
public:
    Mesh(oglplus::Program* program, const std::vector<Vertex>& vertices, 
                    const std::vector<GLuint>& indices);
    void draw();
private:
    const oglplus::Program* _program;
    std::vector<Vertex> _vertices;
    std::vector<GLuint> _indices;
    oglplus::Buffer _faceBuffer;
    oglplus::Buffer _vertexBuffer;
    oglplus::VertexArray _vao;
};

class Model
{
public:
    Model(std::string filename, oglplus::Program* program);
    void draw();
private:
    const oglplus::Program* _program;
    std::vector<std::unique_ptr<Mesh>> _meshes;
};

The issue is with the line

 std::vector<std::unique_ptr<Mesh>> _meshes;

it starts spewing things like

2>c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(593): error C2280: 'std::unique_ptr<Model::Mesh,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' : attempting to reference a deleted function
2>          with
2>          [
2>              _Ty=Model::Mesh
2>          ]
2>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory(1486) : see declaration of 'std::unique_ptr<Model::Mesh,std::default_delete<_Ty>>::unique_ptr'
2>          with
2>          [
2>              _Ty=Model::Mesh
2>          ]
2>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(592) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)'
2>          with
2>          [
2>              _Ty=std::unique_ptr<Model::Mesh,std::default_delete<Model::Mesh>>
2>          ]
2>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(723) : see reference to function template instantiation 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)' being compiled
2>          with
2>          [
2>              _Ty=std::unique_ptr<Model::Mesh,std::default_delete<Model::Mesh>>
2>          ]
2>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\type_traits(572) : see reference to class template instantiation 'std::allocator<_Ty>' being compiled
2>          with
2>          [
2>              _Ty=std::unique_ptr<Model::Mesh,std::default_delete<Model::Mesh>>
2>          ]
2>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector(650) : see reference to class template instantiation 'std::is_empty<_Alloc>' being compiled
2>          with
2>          [
2>              _Alloc=std::allocator<std::unique_ptr<Model::Mesh,std::default_delete<Model::Mesh>>>
2>          ]
2>          c:\users\vitali\projects\3d-stg\source\model\model.hpp(45) : see reference to class template instantiation 'std::vector<std::unique_ptr<Model::Mesh,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>' being compiled
2>          with
2>          [
2>              _Ty=Model::Mesh
2>          ]
2>  model.cpp

I am not using std::vector::resize() or anything like that (in-fact I commented out all uses of my _meshes vector, and even tried commenting the implementation out completely to no avail), so I don't understand why the compiler is giving me issues.

Does anybody have any ideas?


Thank you Preetish Kakkar for finding the issue. It turns out it was an issue with compiler generated functions implicitly using the copy constructor and operator= of the Mesh class forcing the compiler to try and use deleted functions.

Answer

Blackhole picture Blackhole · Mar 31, 2014

I reproduced your problem, below is sample code.

#include <vector>
#include <memory>

class Mesh
{
public: 
    Mesh() {}
    void draw() {}
private:
};

class Model
{
public:
    Model() {}
    void draw() {}
private:
    typedef std::unique_ptr<Mesh> MeshUniquePtr;
    std::vector<MeshUniquePtr> _meshes;
};


int _tmain(int argc, _TCHAR* argv[])
{
    Model m;
    Model m1;
    m = m1; // causes error as you can't copy unique ptr

    return 0;
}

The problem is at some point you are trying to copy two model object which can't be done as unique_ptr is not copyable.