I was under the impression that unique_ptr
could infer class hierarchy in the same way that a normal pointer can, but when I try to overload a function like this:
void func(unique_ptr<Derived1>& d1);
void func(unique_ptr<Derived2>& d2);
And then call one of the functions like this:
unique_ptr<Base> b = make_unique<Derived1>();
func(b);
I get an error saying that no instance of overloaded function "func" matches the argument list
. The runtime type of b is Derived1
, so I expected that the first overload would be called.
Also, when I return a unique_ptr
from a function, the compiler is able to cast (? not sure of the appropriate terminology) a derived class to a base class, so that something like this works:
unique_ptr<Base> create(){
return make_unique<Derived1>();
}
Often in my code I have variables declared as the result of functions like this. They're declared as base but have derived runtime types, and I would like to pass them into one single overloaded function.
How do I overload functions in the same way that I would with regular pointers where class hierarchies are involved?
You are right that the implicit conversion operations of all standard smart pointers model those of raw pointers. This allows the second snippet to compile, i.e.
unique_ptr<Base> create(){
return make_unique<Derived1>();
}
However, there is a misconception about the first snippet, as there is never a builtin implicit downcast-like conversion from base class to derived class. Using normal pointers,
void func(Derived1* d1);
void func(Derived2* d2);
Base* b = new Derived1();
func(b);
won't compile either. This makes sense in a the fundamental OOP sense - look at objects in an inheritance hierarchy through the base class interface, and hide the actual concrete runtime type.
If you need a design with that kind of dispatch, you want to read about the "Visitor" design pattern, which implements a technique called double (or multiple) dispatch. But the amount of boilerplate necessary to realize that gives you a hint why the language doesn't provide this kind of dispatch as a builtin.