Puppy
Puppy

Reputation: 146968

Problem with non-copyable classes

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

Answers (2)

GManNickG
GManNickG

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

Arzar
Arzar

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

Related Questions