Move Constructor, вызывающий базовый класс Move Constructor

У меня есть базовый класс, который в основном завершает присоединение класса к произвольному дескриптору Windows (например, HWND, HFONT) и использует класс политики для присоединения/отсоединения и уничтожения:

// class SmartHandle
template<typename THANDLE, class TWRAPPER, class TPOLICY>
class SmartHandle : boost::noncopyable
{
private:
    TPOLICY*  m_pPolicy;    // Policy
    bool m_bIsTemporary;    // Is this a temporary window?

    SmartHandle();  // no default ctor
    SmartHandle(const SmartHandle<THANDLE, TWRAPPER, TPOLICY>&);    // no cctor
protected:
    THANDLE   m_hHandle;    // Handle to the underlying window

    TPOLICY& policy() {return(*m_pPolicy);};

    // ctor that attaches but is temporary
    SmartHandle(const THANDLE& _handle, bool _temporary) : m_hHandle(_handle)
                                                         , m_bIsTemporary(_temporary)
    {
        m_pPolicy = new TPOLICY(reinterpret_cast<TWRAPPER&>(*this));
        if(_handle)
            m_pPolicy->attach(_handle);
    };  // eo ctor

    // move ctor
    SmartHandle(SmartHandle<THANDLE, TWRAPPER, TPOLICY>&& _rhs) : m_hHandle(_rhs.m_hHandle)
                                                                      , m_bIsTemporary(_rhs.m_bIsTemporary)
    {
        m_pPolicy = new TPOLICY(reinterpret_cast<TWRAPPER&>(*this));
        m_pPolicy->attach(m_hHandle);
        const_cast<SmartHandle&>(_rhs).m_hHandle = NULL;
    };  // eo mtor

    // dtor
    virtual ~SmartHandle()
    {
        if(m_hHandle)
        {
            m_pPolicy->detach(m_hHandle);
            if(!m_bIsTemporary)
                m_pPolicy->destroy(m_hHandle);
            m_hHandle = NULL;
        };
        delete(m_pPolicy);
        m_pPolicy = NULL;
    }; // eo dtor

Обратите внимание, что я объявил конструктор копирования закрытым (без реализации), поскольку я не хочу, чтобы класс копировался, но перемещение разрешено.

Мой класс Window происходит от этого:

    class GALLOW_API Window : SmartHandle<HWND, Window, detail::_hWndPolicy>
    {
    friend class Application;
    private:
        static LRESULT CALLBACK wndProc(HWND _hWnd, UINT _message, WPARAM _wParam, LPARAM _lParam);

        // no copy/default ctor
        Window();
        Window(const Window&);
    protected:

    public:
        static const String ClassName;
        Window(const HWND& _hWnd);
        Window(const WindowCreateInfo& _createInfo);
        Window(Window&& _rhs);
        virtual ~Window();
    };  // eo class Window

Еще раз скопируйте default/copy ctors. Реализация конструктора перемещения:

    Window::Window(Window&& _rhs) : SmartHandle(_rhs)
    {
    };  // eo mtor

Однако во время компиляции я получаю следующую ошибку в первой строке реализации конструктора перемещения:

1>c:\\documents\visual studio 2010\projects\gallow\gallow\window.cpp(81): error C2248: 'gallow::SmartHandle<THANDLE,TWRAPPER,TPOLICY>::SmartHandle' : cannot access private member declared in class 'gallow::SmartHandle<THANDLE,TWRAPPER,TPOLICY>'

Таким образом, создается впечатление, что он пытается вызвать конструктор копирования (который я объявил закрытым), а не конструктор перемещения. Есть ли что-то простое, что мне здесь не хватает?

Заранее спасибо.

РЕДАКТИРОВАТЬ: изменен mtor, чтобы он был неконстантным, ошибка остается. EDIT2: я использую Visual C++ 2010.


person Moo-Juice    schedule 08.12.2010    source источник
comment
Дублировать? stackoverflow.com/questions/4086800/   -  person Éric Malenfant    schedule 08.12.2010
comment
Эрик, спасибо, я не понял. Да, это полностью решило проблему, хотел бы я принять ваш ответ :)   -  person Moo-Juice    schedule 08.12.2010


Ответы (3)


на самом деле должно быть так.

Window::Window(Window&& _rhs) : SmartHandle( std::forward<SmartHandle>( _rhs ) )     {     };  // eo mtor 

http://msdn.microsoft.com/en-us/library/ee390914.aspx

person jbreiding    schedule 01.02.2011

Именованный аргумент не рассматривается как ссылка на rvalue, которую вы должны move использовать.

Window::Window(Window&& _rhs) : SmartHandle(std::move(_rhs))
{
}

Причина, по которой аргумент не рассматривается как rvalue, заключается в том, что его можно использовать дважды, а перемещение обычно изменяет значение, поэтому вы должны явно указать, что эта переменная перемещается.

e.g.

void f(string&& first, string&& second)
{
    string local = first;
    cout << first; // I would be surprised if this is different from `local`

    local = std::move(second); 
    // If I'm surprised after explicitly moving from second it's my problem
}

Лучше использовать move, а не forward в тех случаях, когда вы хотите переместиться, так как а) это понятнее и б) вам нужно указать тип для forward, который является подробным и подверженным ошибкам.

person Motti    schedule 12.12.2010

Конструктор перемещения должен быть T(T&&), а не T(const T&&).

person aschepler    schedule 08.12.2010
comment
Спасибо, я исправил это, но, увы, это не связано с ошибкой, которую я получаю. - person Moo-Juice; 08.12.2010