I have two functions whose signatures I can't change. The first one takes a reference to an object, while the second takes a universal reference to a unique pointer of the same object. I'm not sure how to pass the first argument to the second.
I've tried by passing a new unique ptr with the address of the reference, but because the reference is abstract, the compiler complains about the unimplemented methods.
Here is an example:
// Example program
#include <iostream>
#include <memory>
class MyAbstractClass {
public:
virtual void doSomething() = 0;
};
class MyConcreteClass : public MyAbstractClass {
public:
void doSomething() override {
std::cout << "Hello I do something" << std::endl;
}
};
class MyUserClass {
public:
MyUserClass(MyAbstractClass& mac){
// the line below doesn't work !!
doSomethingElse(std::make_unique<MyAbstractClass>(&mac));
}
void doSomethingElse(std::unique_ptr<MyAbstractClass>&& mac){
mac->doSomething();
}
};
int main() {
MyConcreteClass mcc;
MyUserClass muc(mcc);
}
Your compiler complains because make_unique
calls new
on the type you are trying to instantiate, effectively copying the existing object. Of course, it can't do that, as the class is abstract.
Unless you have a way to guarantee that the reference passed to MyUserClass
is to a dynamic ("heap") variable (and its pointer is not owned, etc.), you cannot just capture its pointer in unique_ptr
and then release it after doSomethingElse
. Even if this is guaranteed, for all you know, doSomethingElse
could still try to delete the pointer itself (unless you know exactly what it does). As you pass it by rvalue reference, the object may not as well be valid after doSomethingElse
returns.
That means you have to make a copy of the object. You can't make a plain copy though. You need to do a copy of the entire, non-abstract, underlying object.
If you are allowed to change signature of the classes, adding a virtual clone
method would to the trick.
If not, a not-absolutely-terrible workaround could be (you need to know beforehand all the types that inherit MyAbstractClass
though) switch(typeid(mac))
and dynamic_cast
.