Reference data elements and move constructor

Assuming the following code:

class ChannelHandle;
class SessionHandle;

typedef ChannelHandle& ChannelHandleRef;
typedef SessionHandle& SessionHandleRef;

class RemoteChannelHandle
{
public:
    RemoteChannelHandle(
        ChannelHandleRef pChannelHandle, SessionHandleRef pSessionHandle);
    RemoteChannelHandle(RemoteChannelHandle&&);
    ~RemoteChannelHandle();

    void CloseChannel();

#ifndef _MSC_VER
    RemoteChannelHandle& operator=(RemoteChannelHandle&&) = delete;
    RemoteChannelHandle(RemoteChannelHandle const&) = delete;
    RemoteChannelHandle& operator=(RemoteChannelHandle const&) = delete;
#endif
private:
    LIBSSH2_CHANNEL* channel;
    ChannelHandleRef channelHandle;
    SessionHandleRef sessionHandle;
};

RemoteChannelHandle::RemoteChannelHandle(
    ChannelHandleRef pChannelHandle, SessionHandleRef pSessionHandle)
    : channel(nullptr), channelHandle(pChannelHandle), sessionHandle(pSessionHandle)
{
    // OPEN SSH CHANNEL
}

RemoteChannelHandle::~RemoteChannelHandle()
{
    try
    {
        CloseChannel();
    }
    catch (...)
    { }
}

void RemoteChannelHandle::CloseChannel()
{
    if (channel == nullptr)
    {
        return;
    }

    // CLOSE SSH CHANNEL. THROW IF SOMETHING GOES WRONG

    channel = nullptr;
}

      

  • RemoteChannelHandle opens an SSH channel, but it takes two steps to clean up (close + free). The first step will be done in ~RemoteChannelHandle()

    , but the second will be done in ChannelHandle dtor; hence the item channelHandle

    , since we need to enter channel

    into it. This link can be fixed by following both steps in ~RemoteChannelHandle()

    .
  • sessionHandle

    contains the LIBSSH2_SESSION*

    required SSH channel to open. Since I do not want to go through LIBSSH2_SESSION*

    , this link cannot be removed.

The problem comes when I define a ctor move for the RemoteChannelHandle. I need to clear the members of the "moved from" instance. However, there is no way to clear the link. So what do you do here?

  • Use (const) std::shared_ptr

    instead of links? I could even use bare pointers as there is no property there. I understand that there is some debate regarding the use of references as data members, but other than moving the ctor, I see no other scenario where I would need to reset by handles (which is why I used references in the first place).
  • Leave the links as they are and create a state data item to check if the object is in a valid state (I can use it channel != nullptr

    for this purpose)?
  • Any other idea?

I've searched for alternatives to this and haven't found a clear answer. This could mean that there isn't really a clear answer, of course.

Thank you for your time.

Edit (in response to Mankarse): ChannelHandle only exists to do step 2 cleanup. Here's a simplified definition:

class ChannelHandle
{
public:
    ChannelHandle();
    ChannelHandle(ChannelHandle&&);
    ~ChannelHandle();

#ifndef _MSC_VER
    ChannelHandle& operator=(ChannelHandle&&) = delete;
    ChannelHandle(ChannelHandle const&) = delete;
    ChannelHandle& operator=(ChannelHandle const&) = delete;
#endif

    LIBSSH2_CHANNEL* GetChannel() { return channel; }
    void SetChannel(LIBSSH2_CHANNEL* pChannel) { channel = pChannel; }

    void FreeChannel();
private:
    LIBSSH2_CHANNEL* channel;
};

      

SessionHandle is a RAII encapsulation for LIBSSH2_SESSION*

. It calls libssh2_session_init()

on ctor and libssh2_session_free()

dtor. Other similar classes will take care of the other steps of initializing / clearing the SSH session, but here we get LIBSSH2_SESSION*

from libssh2 and SessionHandle belongs to it. Once again, a simplified definition:

class SessionHandle
{
public:
    SessionHandle();
    SessionHandle(SessionHandle&&);
    ~SessionHandle();

    void CloseSession();
    LIBSSH2_SESSION* GetSession() { return session; }

#ifndef _MSC_VER
    SessionHandle& operator=(SessionHandle&&) = delete;
    SessionHandle(SessionHandle const&) = delete;
    SessionHandle& operator=(SessionHandle const&) = delete;
#endif
private:    
    LIBSSH2_SESSION *session;
};

      

+3


source to share


1 answer


You yourself answered the question:



I could even use bare pointers since there was no participation there.

+3


source







All Articles