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

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.

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.

Related

std::array of a private nested struct can't be initialized (error C2248)

The following code compiles correctly in ideone (C++14, link):
#include <iostream>
#include <array>
#include <vector>
class Foo {
public:
void foo() { auto stashedCells = cells; }
private:
struct Bar { std::vector<int> choices; };
std::array<Bar, 10> cells;
};
int main() {
Foo foo;
foo.foo();
}
However, in Visual Studio 2015, it produces the following errors:
1> main.cpp
1>c:\program files (x86)\microsoft visual studio 14.0\vc\include\array(220): error C2248: 'Foo::Bar': cannot access private struct declared in class 'Foo'
1> c:\users\alcedine\documents\visual studio 2015\projects\mvce\mvce\main.cpp(9): note: see declaration of 'Foo::Bar'
1> c:\users\alcedine\documents\visual studio 2015\projects\mvce\mvce\main.cpp(5): note: see declaration of 'Foo'
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\array(220): note: This diagnostic occurred in the compiler generated function 'std::array<Foo::Bar,10>::array(const std::array<Foo::Bar,10> &)'
The unit compiles successfully if Foo::Bar is empty or contains just an int, so it doesn't seem to be due to the access specifier, compiler messages to that effect notwithstanding.
Is this due to some difference between C++11 and C++14? Is Visual Studio behaving correctly here?
This appears to be a bug of MSVC2015.
The problem is related to the copy construction of the array that you make in foo(). It seems not directly related to the implementation of std::array, because boost::array produces exactly the same error.
A workaround is to split the construction from the copy, for example:
void foo()
{
decltype(cells) stashedCells; // this works
stashedCells = cells; // this works
}
Or:
void foo()
{
std::array<Bar, 10> stashedCells;
stashedCells = cells;
}
Other potential workarounds such as using a public typedef or type alias for the array and/or Bar always fail. The error only disapears when making Bar public.

c++ unordered_multimap insert hash

I'm going crazy over here. I have search google to find 1 single decent example where people use a unordered_map together with enum class and a hash function without any luck. Those i manage to find always end up saying "use map instead".
I'm trying to do the following:
Enum class facing is the direction my sprite is looking at.
Enum class Action is the action my sprite is doing.
Animation is a class that holds different animations which i will call later.
The container should look like this:
map
There can be more than 1 FACING in the map as key and there can be more than one ACTION in the pair.
Example:
map<LEFT, pair<ATTACK, attackAnimation>
map<LEFT, pair<IDLE, idleAnimation>
map<LEFTUP, pair<IDLE, idleAnimation>
This is an simplified everything
#include <iostream>
#include <unordered_map>
#include <string>
#include <memory>
template <typename T>
struct Hash
{
typedef typename std::underlying_type<T>::type underlyingType;
typedef typename std::hash<underlyingType>::result_type resultType;
resultType operator()(const T& arg) const
{
std::hash<underlyingType> hasher;
return hasher(static_cast<underlyingType>(arg));
}
};
class Animation
{
private:
std::string str;
public:
Animation(std::string _string)
{
this->str = _string;
}
std::string& GetString()
{
return this->str;
}
};
class Bullshit
{
public:
enum class Action
{
Attack,
Move
};
enum class Facing
{
Right,
Up,
Left
};
Bullshit()
{
}
std::unordered_multimap<Bullshit::Facing, std::pair<Bullshit::Action, std::unique_ptr<Animation>>,Hash<Bullshit::Facing>>& GetlistAnimation()
{
return this->listAnimation;
}
private:
std::unordered_multimap<Bullshit::Facing, std::pair<Bullshit::Action, std::unique_ptr<Animation>>,Hash<Bullshit::Facing>> listAnimation;
};
int main()
{
Bullshit bull;
auto myList = bull.GetlistAnimation();
std::unique_ptr<Animation> anim(new Animation("test"));
myList.insert(std::make_pair(Bullshit::Facing::Up, std::make_pair(Bullshit::Action::Attack, std::move(anim))));
std::cin.get();
return 0;
}
Error code:
error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
1> with
1> [
1> _Ty=Animation
1> ]
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\memory(1447) : see declaration of 'std::unique_ptr<_Ty>::unique_ptr'
1> with
1> [
1> _Ty=Animation
1> ]
1> This diagnostic occurred in the compiler generated function 'std::pair<_Ty1,_Ty2>::pair(const std::pair<_Ty1,_Ty2> &)'
1> with
1> [
1> _Ty1=Bullshit::Action,
1> _Ty2=std::unique_ptr<Animation>
1> ]
Here
auto myList = bull.GetlistAnimation();
the type deduced for myList is std::unordered_map<.....>, that is, it's not a reference. And the copy can't be created because the map contains unique_ptrs. What you meant is
auto& myList = bull.GetlistAnimation();
or in C++14,
decltype(auto) myList = bull.GetlistAnimation();
The problem has nothing to do with unordered_map or hash functions. It's the std::unique_ptr, which is uncopyable, and your GetlistAnimation attempts to copy it (indirectly).
How to correctly fix this depends on what you want to achieve.
A quick fix would be to use std::shared_ptr instead:
std::unordered_map<Bullshit::Facing, std::pair<Bullshit::Action, std::shared_ptr<Animation>>,Hash<Bullshit::Facing>>& GetlistAnimation()
{
return this->listAnimation;
}
private:
std::unordered_map<Bullshit::Facing, std::pair<Bullshit::Action, std::shared_ptr<Animation>>,Hash<Bullshit::Facing>> listAnimation;
[...]
std::shared_ptr<Animation> anim(new Animation("test"));
myList.insert(std::make_pair(Bullshit::Facing::Up, std::make_pair(Bullshit::Action::Attack, anim)));
(By the way, you should use std::make_shared and std::make_unique.)
A fix which may be quick and correct (again, depending on what you want to achieve) is to get rid of the pointer logic altogether and just use Animation directly:
std::unordered_map<Bullshit::Facing, std::pair<Bullshit::Action, Animation>,Hash<Bullshit::Facing>>& GetlistAnimation()
{
return this->listAnimation;
}
private:
std::unordered_map<Bullshit::Facing, std::pair<Bullshit::Action, Animation>,Hash<Bullshit::Facing>> listAnimation;
[...]
Animation anim("test");
myList.insert(std::make_pair(Bullshit::Facing::Up, std::make_pair(Bullshit::Action::Attack, anim)));

Failed to compile while the argument is lambda. [using hippomocks]

I wrote an unit test with hippomocks, but got error while compiling it.
The compiler is VS 2010.
How can I fix it ?
#include "hippomocks.h"
#include <functional>
using namespace HippoMocks;
struct A
{
virtual void f(std::function<void (int)> arg);
};
int main(void)
{
MockRepository mock;
A* aptr = mock.Mock<A>();
mock.ExpectCall(aptr, A::f); // error
return 0;
}
The output is :
main.cpp
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\xlocale(323) : wa
rning C4530: C++ exception handler used, but unwind semantics are not enabled. S
pecify /EHsc
c:\users\cong\project\test\test\hippomocks.h(466) : error C2593: 'operator <<' i
s ambiguous
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\ostream(2
06): could be 'std::basic_ostream<_Elem,_Traits> &std::basic_ostream<_Elem,_Trai
ts>::operator <<(std::_Bool)'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
c:\users\cong\project\test\test\hippomocks.h(441): or 'std::ostrea
m &HippoMocks::operator <<(std::ostream &,const HippoMocks::NotPrintable &)'
while trying to match the argument list '(std::ostream, std::tr1::functi
on<_Fty>)'
with
[
_Fty=void (int)
]
c:\users\cong\project\test\test\hippomocks.h(463) : while compiling clas
s template member function 'void HippoMocks::printArg<T>::print(std::ostream &,T
,bool)'
with
[
T=std::tr1::function<void (int)>
]
c:\users\cong\project\test\test\hippomocks.h(614) : see reference to cla
ss template instantiation 'HippoMocks::printArg<T>' being compiled
with
[
T=std::tr1::function<void (int)>
]
Enhancing #dascandy's comment here is how his method can look like. Place it after including hippomocks.h:
template<>
struct printArg<std::function<void (int)> >
{
static inline void print(std::ostream &os, std::function<void (int)> arg, bool withComma)
{
if (withComma)
{
os << ",";
}
if (arg)
{
os << "true";
}
else
{
os << "false";
}
}
};
Note that I didn't test this very example but rather took our solution and adapted the type to the original post's example. I'd be happy to know whether this works for you.

QtConcurrent::blockingMapped() and std::vector<> bug

It seems that QtConcurrent works fine with QT containers (QList and QVector), but fails with the STL containers, as opposed to what is claimed in the documentation
Here are the dummy functions I want to use on my containers :
void addOne(int & i)
{
++i;
}
int addOneC(const int & i)
{
return i+1;
}
Examples of what works :
int main( int argc, char** argv )
{
// Qt containers
QList<int> l;
l << 1 << 2 << 4 << 3;
QList<int> l1 = QtConcurrent::blockingMapped(l, addOneC);
QtConcurrent::blockingMap(l1, addOne);
// Standard containers
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(4);
v.push_back(3);
QtConcurrent::blockingMap(v, addOne);
}
What does not work :
int main( int argc, char** argv )
{
// Standard containers
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(4);
v.push_back(3);
vector<int> v1 = QtConcurrent::blockingMapped(v, addOneC);
}
It cause a compilation error with atrociously long and obfuscate template errors.
If anyone knew why, it would really help! Thanks!
The error log :
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\xutility(442) : error C2825: '_Alloc': must be a class or namespace when followed by '::'
1> .\main.cpp(187) : see reference to class template instantiation 'std::_Container_base_aux_alloc_real<_Alloc>' being compiled
1> with
1> [
1> _Alloc=int
1> ]
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\xutility(442) : error C2903: 'rebind' : symbol is neither a class template nor a function template
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\xutility(442) : error C2039: 'rebind' : is not a member of 'global namespace''
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\xutility(442) : error C2143: syntax error : missing ';' before '<'
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\xutility(442) : error C2039: 'other' : is not a member of 'global namespace''
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\xutility(442) : error C2238: unexpected token(s) preceding ';'
1>.\main.cpp(187) : error C2248: 'std::_Container_base_aux_alloc_real<_Alloc>::~_Container_base_aux_alloc_real' : cannot access protected member declared in class 'std::_Container_base_aux_alloc_real<_Alloc>'
1> with
1> [
1> _Alloc=int
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\xutility(435) : see declaration of 'std::_Container_base_aux_alloc_real<_Alloc>::~_Container_base_aux_alloc_real'
1> with
1> [
1> _Alloc=int
1> ]
1>.\main.cpp(187) : error C2440: 'initializing' : cannot convert from 'std::_Container_base_aux_alloc_real<_Alloc>' to 'std::vector<_Ty>'
1> with
1> [
1> _Alloc=int
1> ]
1> and
1> [
1> _Ty=int
1> ]
1> No constructor could take the source type, or constructor overload resolution was ambiguous
I think you should explicitly give the type of the container to the blockingMapped.
int main( int argc, char** argv )
{
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(4);
v.push_back(3);
std::vector<int> v1 = QtConcurrent::blockingMapped<std::vector<int> >(v, addOneC);
}
Compile and give me the expected result in the simple example you gave.

Why doesn't this C++ template code compile?

Does anyone know why this will not compile? I've tried both VS 2008 and GCC 4.something and both spit out errors. It doesn't matter whether or not I'm referencing "ThisFunctionDoesNotCompile()".
I can workaround this by just passing 'InternalType' as a second template parameter to Base, but I'm still curious why this comes up as an error.
#include <iostream>
using namespace std;
class DataClass
{
public:
int m_data;
};
template<typename DerivedType>
class Base
{
public:
int ThisFunctionCompiles()
{
// No problems here.
typename DerivedType::InternalType temp;
temp.m_data = 5;
return temp.m_data;
}
// error C2039: 'InternalType' : is not a member of 'Derived<InInternalType>'
typename DerivedType::InternalType ThisFunctionDoesNotCompile()
{
return static_cast<DerivedType*>(this)->GetInternalData();
}
};
template<typename InInternalType>
class Derived : public Base<Derived<InInternalType> >
{
public:
typedef InInternalType InternalType;
InternalType GetInternalData()
{
return m_internalData;
}
private:
InternalType m_internalData;
public:
void SetInternalData( int newVal )
{
m_internalData.m_data = newVal;
}
};
int main()
{
Derived<DataClass> testDerived;
testDerived.SetInternalData( 3 );
cout << testDerived.GetInternalData().m_data << endl;
cout << testDerived.ThisFunctionCompiles() << endl;
// The compiler gives an error regardless of whether or not this is commented out.
//cout << testDerived.ThisFunctionDoesNotCompile().m_data << endl;
return 0;
}
These are the errors I get in VS 2008:
1>e:\test\generaltestprogram\generaltestprogram\main.cpp(27) : error C2039: 'InternalType' : is not a member of 'Derived<InInternalType>'
1> with
1> [
1> InInternalType=DataClass
1> ]
1> e:\test\generaltestprogram\generaltestprogram\main.cpp(35) : see reference to class template instantiation 'Base<DerivedType>' being compiled
1> with
1> [
1> DerivedType=Derived<DataClass>
1> ]
1> e:\test\generaltestprogram\generaltestprogram\main.cpp(58) : see reference to class template instantiation 'Derived<InInternalType>' being compiled
1> with
1> [
1> InInternalType=DataClass
1> ]
1>e:\test\generaltestprogram\generaltestprogram\main.cpp(27) : error C2146: syntax error : missing ';' before identifier 'ThisFunctionDoesNotCompile'
1>e:\test\generaltestprogram\generaltestprogram\main.cpp(27) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>e:\test\generaltestprogram\generaltestprogram\main.cpp(28) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>e:\test\generaltestprogram\generaltestprogram\main.cpp(28) : warning C4183: 'ThisFunctionDoesNotCompile': missing return type; assumed to be a member function returning 'int'
And these are what GCC gives me:
main.cpp: In instantiation of 'Base<Derived<DataClass> >':
main.cpp:96: instantiated from 'Derived<DataClass>'
main.cpp:119: instantiated from here
main.cpp:88: error: no type named 'InternalType' in 'class Derived<DataClass>'
At the time that the templated class Base is instantiated as a parent of the class Derived, the class Derived is not a complete type.
Since Base<Derived<DataClass> > is a parent class of Derived<DataClass>, it must be instantiated before Derived<DataClass> can be instantiated. So when the class Base<Derived<DataClass> > is built from the template, Derived<DataClass> behaves as if it were a forward declaration. And as you're probably aware, you can't reference members of incomplete types, nor can your forward-declare nested types, so you're out of luck here.
This, by the way, is why it's difficult to implement a properly covariant clone() method using templates. See here and here (mine).