c++move

Is there a way to call the default move operator from a non-default one?


I have this class:

struct Handle
{
    int* ptr_to_something;
    void operator=(Handle&& other)
    {
        ptr_to_something = other.ptr_to_something;
        this->member1 = other.member1;
        this->member2 = other.member2;
        this->member3 = other.member3;
        
        other.ptr_to_something = nullptr;
        
    }
    
    int member1;
    int member2;
    int member3;
};

What I hate is possibility that new members might be added, and I'll have to remember to add them to the operator. Is there possibly a way I could call the default operator and then add that teensy little but that sets the other ptr to null after it?


Solution

  • You can have a base class with a defaulted move operator:

    struct HandlerBase {
        int* ptr_to_something;
        int member1;
        int member2;
        int member3;
    };
    
    struct Handler : HandlerBase {
        void operator=(Handler&& other) {
            HandlerBase::operator=(std::move(other));
            other.ptr_to_something = nullptr;
        }
    };
    

    Or you can make the defaulted move operator do what you want by making ptr_to_something a class whose operator= does what you want:

    template<typename T>
    struct PtrThatResetsOnMove {
        T* value;
    
        constexpr explicit(false) PtrThatResetsOnMove(T* value) noexcept : value(value) {}
        constexpr PtrThatResetsOnMove(PtrThatResetsOnMove&& other) noexcept : value(std::exchange(other.value, nullptr)) {}
        constexpr PtrThatResetsOnMove& operator=(PtrThatResetsOnMove&& other) noexcept {
            value = std::exchange(other.value, nullptr);
            return *this;
        }
        ~PtrThatResetsOnMove() = default;
    };
    
    struct Handler {
        PtrThatResetsOnMove<int> ptr_to_something;
        int member1;
        int member2;
        int member3;
    };
    

    Or you can put the other members in a different class with a defaulted operator:

    struct HandlerMembers {
        int member1;
        int member2;
        int member3;
    };
    
    struct Handler {
        int* ptr_to_something;
        HandlerMembers members;
        void operator=(Handler&& other) {
           ptr_to_something = other.ptr_to_something;
           members = std::move(other.members);
           other.ptr_to_something = nullptr;
        }
    };