Reputation: 146968
I've got some non-copyable classes. I don't invoke any of the copy operators or constructor, and this code compiles fine. But then I upgraded to Visual Studio 2010 Ultimate instead of Professional. Now the compiler is calling the copy constructor- even when the move constructor should be invoked. For example, in the following snippet:
inline D3D9Mesh CreateSphere(D3D9Render& render, float radius, float slices) {
D3D9Mesh retval(render);
/* ... */
return std::move(retval);
}
Error: Cannot create copy constructor, because the class is non-copyable. However, I quite explicitly moved it.
Edit:
class D3D9Mesh
: public Monitor<D3D9Mesh>
{
public:
std::unique_ptr<ID3DXMesh, COMDeleter> Mesh;
std::unique_ptr<ID3DXBuffer, COMDeleter> Adjacency;
inline D3D9Mesh(D3D9Render& ref)
: Monitor<D3D9Mesh>(&ref)
{
}
};
where Monitor is a simple class that is copyable/etc. It's the unique_ptrs which are clearly not kosher for the compiler.
Monitor's code:
class D3DCommon {};
template<typename T> class Monitor : public D3DCommon {
protected:
D3D9Render* render;
Monitor(D3D9Render* ptr)
: render(ptr) {
render->AddPointer(static_cast<T*>(this));
}
Monitor(Monitor&& ref) {
render->AddPointer(static_cast<T*>(this));
}
Monitor(const Monitor& ref) {
render->AddPointer(static_cast<T*>(this));
}
~Monitor() {
render->RemovePointer(static_cast<T*>(this));
}
public:
D3D9Render& GetRender() {
return *render;
}
};
Upvotes: 2
Views: 458
Reputation: 504103
MSVC doesn't do implicit move constructors. You need to make it yourself:
class D3D9Mesh
: public Monitor<D3D9Mesh>
{
public:
inline D3D9Mesh(D3D9Render& ref)
: Monitor(&ref) // don't need to re-state template argument, by the way
{
}
D3D9Mesh(D3D9Mesh&& other)
: Monitor(std::move(other))
{}
};
Now it's movable.
Upvotes: 1
Reputation: 14317
That's weird. How is your D3D9Mesh class implemented ?
The following code compiles fine for me with vs2010 ultimate :
#include <iostream>
struct S
{
S(){std::cout << "ctor\n";}
S(S&&){std::cout << "move ctor\n";}
S& operator=(S&&){std::cout << "move op=\n";return *this;}
private:
S(const S&);
S& operator=(const S&);
};
inline S CreateSphere()
{
S s;
return s;
}
int main()
{
S s = CreateSphere(); // NRVO
s = CreateSphere(); // move
}
PS : Don't write return std::move(something) if "something" is a local variable created in the function. The compiler already know that the returning a local variable from a function is a temporary(an rvalue). ReCasting yourself with std::move will not make it move better, however it will prevent on vs2010 some optimization such as NRVO.
Upvotes: 1