Как получить указатель на новую переменную при использовании конструктора перемещения - PullRequest
0 голосов
/ 09 апреля 2020

Итак, у меня есть этот код:

//movable_ptr.hpp
//Michal Cermak

template<typename T> class movable_ptr;

template<typename T> class enable_movable_ptr {
public:
    //default constructor
    enable_movable_ptr() {};

    //move constructor and assignment
    enable_movable_ptr(enable_movable_ptr<T>&& p) {
        first_ = p.getFirst();
        p.retarget_to(this);
    };
    enable_movable_ptr<T>& operator=(enable_movable_ptr<T>&& p) {
        if (this != &p)
        {
            first_ = p.getFirst();
            p.retarget_to(this);
            delete &p;
        }
        return *this;
    };

    //retargets all pointers in the linked list to a new address
    void retarget_to(T* p)
    {
        if (first_ != nullptr)
        {
            auto current = first_;
            do
            {
                current->set(p);
                current = current->getNext();
            } while (current != first_);
        }
    };

    movable_ptr<T>* getFirst() { return first_; };
    void setFirst(movable_ptr<T>* p) { first_ = p; };
private:
    movable_ptr<T>* first_ = nullptr;
};

template<typename T> class movable_ptr {
public:
    //constructors and stuff...

    //access to variables
    T* get() {return ptr_; };
    void set(T* p) { ptr_ = p; };
    movable_ptr<T>* getNext() { return next_; };
    void setNext(movable_ptr<T>* p) { next_ = p; };
    movable_ptr<T>* getPrevious() {return prev_; };
    void setPrevious(movable_ptr<T>* p) { prev_ = p; };

private:
    T* ptr_ = nullptr;
    movable_ptr<T>* next_ = this;
    movable_ptr<T>* prev_ = this;
};

Моя проблема в том, что мне нужно дать T * для retarget_to, но я использую retarget_to(this) в конструкторе перемещения и присваивании в enable_movable_ptr. Это проходит enable_movable_ptr<T> * вместо T *. Дело в том, я предполагаю, что T наследуется от enable_movable_ptr, который никогда не будет использоваться напрямую, только через объект, который наследуется от него. Например:

class A : public enable_movable_ptr<A>
{
public:
    int val;

    A(int val) : val(val) {}
};

И затем используется так:

A x(42);
A y = move(x);

В этом случае this будет enable_movable_ptr<A> *, но мне нужно что-то, что даст мне A * вместо. По сути, мне нужен указатель на lvalue оператора =, находящийся внутри перегрузки указанного оператора. Есть ли способ сделать это или я прошу что-то невозможное?

1 Ответ

0 голосов
/ 09 апреля 2020

Я не совсем понял ваш вопрос, потому что не ясно, чего вы хотите достичь с помощью этого enable_movable_ptr класса. Я думаю, что ваш способ написания operator= является неправильным. Вы пытаетесь явно вызвать delete для указателя на r-значение (которое может сначала быть размещено в стеке, и, более того, вероятно, будет впоследствии уничтожено в любом случае с помощью какого-либо другого механизма).

Я бы предложил рассмотреть copy- and-swap подход для operator=, это позволит вам не беспокоиться о проверке, если вы присваиваете объект самому себе. Подпись будет enable_movable_ptr<T>& operator=(enable_movable_ptr<T> other) (примечание передается по значению).

...