Move Constructor calling base-class Move Constructor

懵懂的女人 提交于 2020-01-03 06:59:06

问题


I have a base class that basically wraps up attaching a class to a arbitrary windows handle (e.g, HWND, HFONT), and uses a policy class to attach/detach and destroy:

// 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

Note that I've declared the copy constructor private (with no implementation) as I do not want the class to be copied, but a move is allowed.

My Window class derives from this:

    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

Once again, copy default/copy ctors. The implementation of the move constructor is:

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

However, during compilation I get the following error on the first line of the move constructor implementation:

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>'

So, it appears as if it is trying to call the copy constructor (which I've declared private) rather than the move constructor. Is there something simple I am missing here?

Thanks in advance.

EDIT: Modified mtor so it was non-const, error remains. EDIT2: I am using Visual C++ 2010.


回答1:


actually it should be like this.

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

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




回答2:


A named argument isn't treated as a rvalue reference you have to move it.

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

The reason an argument isn't treated as an rvalue is that it can be used twice and moving typically changes the value therefore you have to be explicit about knowing that this variable is moved from.

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
}

It's better to use move rather than forward in cases when you want to move since a) it's clearer and b) you need to specify a type for forward which is verbose and error prone.




回答3:


A move constructor should be T(T&&), not T(const T&&).



来源:https://stackoverflow.com/questions/4390888/move-constructor-calling-base-class-move-constructor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!