Home > Mobile >  Is there a shorthand method to writing move constructors?
Is there a shorthand method to writing move constructors?

Time:08-13

I have a class with one strong pointer and a lot of object members. Writing copy and move constructors for an object like this involves a lot of tedious copy/pasting, however...

Is there any way to shorten this, without giving up my beautiful naked pointer? Like if I could perform the default generated move operation, with just one extra instruction to nullify the naked pointer afterwards?

class Example {
public:
    Example() 
        : m_multiplexDevice(getDevice(B737M_mpDevice, true))
    {
        engageDevice(m_multiplexDevice);
    }

    Example(Example && other)
        : m_multiplexDevice     (other.m_multiplexDevice    )
        , m_pilotStack          (std::move(other.m_pilotStack       ))
        , m_pasStack            (std::move(other.m_pasStack         ))
        , m_pitchAttackLimits   (std::move(other.m_pitchAttackLimits))
        , m_yawToPitchBalance   (std::move(other.m_yawToPitchBalance))
        , m_engineBalance       (std::move(other.m_engineBalance    ))
    { 
        other.m_multiplexDevice = NULL;
    }

    Example & operator=(Example && other) {
        if (this != &other) {
            // ignore that this is incorrect (not properly destroying in assignment), 
            // working with client code that kinda sucks
            m_multiplexDevice    = other.m_multiplexDevice;
            m_pilotStack         = std::move(other.m_pilotStack         );
            m_pasStack           = std::move(other.m_pasStack           );
            m_pitchAttackLimits  = std::move(other.m_yawToPitchBalance  );
            m_yawToPitchBalance  = std::move(other.m_yawToPitchBalance  );
            m_engineBalance      = std::move(other.m_engineBalance      );
            m_multiplexDevice = NULL;
        }
        return *this;
    }

    Example(const Example & other) =delete;

    Example & operator=(const Example & other) =delete;

    ~Example() {
        if (m_multiplexDevice)
            disengageDevice(m_multiplexDevice);
        delete m_multiplexDevice;
    }

private:
    char STRONG * m_multiplexDevice;
    std::vector<uint32> m_pilotStack;
    std::vector<uint32> m_pasStack;
    std::vector<uint32> m_pitchAttackLimits;
    std::vector<uint32> m_yawToPitchBalance;
    std::vector<uint32> m_engineBalance;
    // ... etc
};

CodePudding user response:

Use a unique_ptr with a custom deleter.

#include <memory>
#include <vector>
#include <cstdint>
#define STRONG /* ??? */
void disengageDevice(char STRONG*);
#define B737M_mpDevice 1
char STRONG *getDevice(int, ...);
void engageDevice(char STRONG *);


class Example {
public:
    Example() 
        : m_multiplexDevice(
            getDevice(B737M_mpDevice, true),
            deconstruct_m_multiplexDevice)
    {
        engageDevice(m_multiplexDevice.get());
    }

    static void deconstruct_m_multiplexDevice(char STRONG *p) {
        if (p) {
            disengageDevice(p);
            delete p;
        }
    }

private:
    std::unique_ptr<
        char STRONG,
        decltype(&deconstruct_m_multiplexDevice)
    > m_multiplexDevice;
    std::vector<uint32_t> m_pilotStack;
    std::vector<uint32_t> m_pasStack;
    std::vector<uint32_t> m_pitchAttackLimits;
    std::vector<uint32_t> m_yawToPitchBalance;
    std::vector<uint32_t> m_engineBalance;
    // ... etc
};
  • Related