I have a problem in making a static_cast
of an unique_ptr
void *
by passing arguments to the constructor. In particular, what you see in the object3
.
It is important that the solution is at compile time, and the type must be the same for smart pointers as for stacked objects.
Any solution?
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;
}
result:
1
2
0
4
Maybe you want:
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;
};
so you won't have dangling pointer anymore.
For more pointer semantic-like:
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;
};
What you are noticing is undefined behavior.
The lifetime of the unique_ptr is not what you expect.
Object<Test> object3 = std::make_unique<Test>(3);
cout << object3->num << endl; // print 0 ¿?¿?¿?
You make a temporary unique_ptr, after which in the constructor you take the address of that temporary.
Object(std::unique_ptr<T>&& v) : value(static_cast<std::unique_ptr<T>*>(std::move(&v))) {}
In this statement, you take the address of that unique_ptr, after which you move that pointer. For a raw pointer, that has no extra effect.
You can have the same unexpected result for every other of your statements as all of them use temporaries.
Note that you also wrote a reinterpret_cast from the unique_ptr to a raw pointer.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.