static_cast для unique_ptr в void *, с аргументами конструктора - PullRequest
0 голосов
/ 11 мая 2018

У меня проблема с созданием static_cast из unique_ptr void * путем передачи аргументов конструктору.В частности, то, что вы видите в object3.

Важно, чтобы решение находилось во время компиляции, и тип должен быть таким же для интеллектуальных указателей, как и для сложенных объектов.

Любое решение?

class Test {
public:
    Test(){}
    Test(int n) : num(n) {}
    int num;
};

template<typename T>
class Object {
public:
    Object(T&& v) : value(static_cast<T*>(std::move(&v))) {}
    Object(const T& v) : value(static_cast<T*>(&v)) {}

    Object(std::unique_ptr<T>&& v) : value(static_cast<std::unique_ptr<T>*>(std::move(&v))) {}
    Object(const std::unique_ptr<T>& v) : value(static_cast<std::unique_ptr<T>*>(&v)) {}

    T* operator->() { return static_cast<T*>(value); }
private:
    void* value;
};

int main(int argc, char *argv[]) {

    Object<Test> object1 = Test(1);
    cout << object1->num << endl; // print 1

    Object<Test> object2 = Test();
    object2->num = 2;
    cout << object2->num << endl; // print 2

    Object<Test> object3 = std::make_unique<Test>(3);
    cout << object3->num << endl; // print 0 ¿?¿?¿?

    Object<Test> object4 = std::make_unique<Test>();
    object4->num = 4;
    cout << object4->num << endl; // print 4

    return 0;
}

результат:

1
2
0
4

Ответы [ 2 ]

0 голосов
/ 11 мая 2018

То, что вы заметили, это неопределенное поведение.

Время жизни unique_ptr не соответствует ожидаемому.

Object<Test> object3 = std::make_unique<Test>(3);
cout << object3->num << endl; // print 0 ¿?¿?¿?

Вы создаете временный unique_ptr, после чего в конструкторе вы беретеадрес этого временного.

Object(std::unique_ptr<T>&& v) : value(static_cast<std::unique_ptr<T>*>(std::move(&v))) {}

В этом операторе вы берете адрес этого unique_ptr, после которого вы перемещаете этот указатель.Для необработанного указателя это не имеет никакого дополнительного эффекта.

Вы можете получить тот же неожиданный результат для всех ваших операторов, поскольку все они используют временные значения.

Обратите внимание, что вы также написали reinterpret_castиз unique_ptr в необработанный указатель.

0 голосов
/ 11 мая 2018

Может быть, вы хотите:

template<typename T>
class Object {
public:
    Object(const T& v) : value(v) {}
    Object(const std::unique_ptr<T>& v) : value(*v) {}

    T* operator->() { return &value; }
private:
    T value;
};

чтобы у вас больше не было висящего указателя.

Демо

Для большего количества семантических указателей:

template<typename T>
class Object {
public:
    Object(const T& v) : value(std::make_shared(v)) {}
    Object(std::unique_ptr<T>&& v) : value(std::move(v)) {}

    T* operator->() { return value.get(); }
private:
    std::shared_pointer<T> value;
};

Демо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...