Проблема с не копируемыми классами - PullRequest
2 голосов
/ 05 января 2011

У меня есть несколько не копируемых классов. Я не вызываю ни один из операторов копирования или конструктор, и этот код компилируется нормально. Но затем я обновился до Visual Studio 2010 Ultimate вместо Professional. Теперь компилятор вызывает конструктор копирования - даже когда должен быть вызван конструктор перемещения. Например, в следующем фрагменте:

inline D3D9Mesh CreateSphere(D3D9Render& render, float radius, float slices) {
    D3D9Mesh retval(render);
    /* ... */
    return std::move(retval);
}

Ошибка: невозможно создать конструктор копирования, так как класс не подлежит копированию. Тем не менее, я совершенно явно переместил его.

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) 
    {
    }
};

где Monitor - это простой класс, который можно копировать / etc. Это unique_ptrs, явно не кошерный для компилятора.

Код монитора:

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;
    }
};

Ответы [ 2 ]

1 голос
/ 07 января 2011

MSVC не делает неявных конструкторов перемещения. Вам нужно сделать это самостоятельно:

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))
    {}
};

Теперь это подвижно.

1 голос
/ 05 января 2011

Странно. Как реализован ваш класс D3D9Mesh?
Следующий код прекрасно компилируется для меня с 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: не пишите return std :: move (что-то), если "что-то" является локальной переменной, созданной в функции. Компилятор уже знает, что возвращение локальной функции из функции является временным (значение). Пересчет с помощью std :: move не сделает его лучше, но на vs2010 он предотвратит некоторую оптимизацию, такую ​​как NRVO.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...