#include <iostream>
using namespace std;
template <typename T>
class SmartPtr {
public:
SmartPtr(T* ptr = 0) : pointee(ptr) {}
SmartPtr(SmartPtr& rhs) {
pointee = rhs.pointee;
rhs.pointee = 0;
}
SmartPtr<T>& operator=(SmartPtr<T>& rhs) {
if(this == &rhs)
return *this;
pointee = rhs.pointee;
rhs.pointee = 0;
}
~SmartPtr() { delete pointee; }
//operator->, etc. irrelevant here.
//member template for type conversion
template <typename NewType>
operator SmartPtr<NewType>() {
return SmartPtr<NewType>(pointee);
}
private:
T* pointee;
};
class Remote {};
class Base : public Remote {};
class Derived : public Base {};
void foo(const SmartPtr<Remote>& p) { cout << "remote" << endl;}
void foo(const SmartPtr<Base>& p) { cout << "base" << endl;}
template <>
class SmartPtr<Base> {
public:
SmartPtr(Derived* p) : pointee(static_cast<Base*>(p)){}
private:
Base* pointee;
};
int main() {
SmartPtr<Derived> d(new Derived());
//foo(d); //ambiguous call. How to remove ambiguity?
foo(static_cast<SmartPtr<Base>>(d)); //does not compile either.
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KY2xhc3MgU21hcnRQdHIgewpwdWJsaWM6CiAgU21hcnRQdHIoVCogcHRyID0gMCkgOiBwb2ludGVlKHB0cikge30KICBTbWFydFB0cihTbWFydFB0ciYgcmhzKSB7CiAgICBwb2ludGVlID0gcmhzLnBvaW50ZWU7CglyaHMucG9pbnRlZSA9IDA7CiAgfQogIFNtYXJ0UHRyPFQ+JiBvcGVyYXRvcj0oU21hcnRQdHI8VD4mIHJocykgewogIAlpZih0aGlzID09ICZyaHMpCiAgCSAgcmV0dXJuICp0aGlzOwoJICBwb2ludGVlID0gcmhzLnBvaW50ZWU7CgkgIHJocy5wb2ludGVlID0gMDsKICB9CiAgflNtYXJ0UHRyKCkgeyBkZWxldGUgcG9pbnRlZTsgfQogIC8vb3BlcmF0b3ItPiwgZXRjLiBpcnJlbGV2YW50IGhlcmUuCiAgLy9tZW1iZXIgdGVtcGxhdGUgZm9yIHR5cGUgY29udmVyc2lvbgogIHRlbXBsYXRlIDx0eXBlbmFtZSBOZXdUeXBlPgogIG9wZXJhdG9yIFNtYXJ0UHRyPE5ld1R5cGU+KCkgewogIAlyZXR1cm4gU21hcnRQdHI8TmV3VHlwZT4ocG9pbnRlZSk7CiAgfQpwcml2YXRlOgogIFQqIHBvaW50ZWU7Cn07CmNsYXNzIFJlbW90ZSB7fTsKY2xhc3MgQmFzZSA6IHB1YmxpYyBSZW1vdGUge307CmNsYXNzIERlcml2ZWQgOiBwdWJsaWMgQmFzZSB7fTsKdm9pZCBmb28oY29uc3QgU21hcnRQdHI8UmVtb3RlPiYgcCkgeyBjb3V0IDw8ICJyZW1vdGUiIDw8IGVuZGw7fQp2b2lkIGZvbyhjb25zdCBTbWFydFB0cjxCYXNlPiYgcCkgeyBjb3V0IDw8ICJiYXNlIiA8PCBlbmRsO30KdGVtcGxhdGUgPD4KY2xhc3MgU21hcnRQdHI8QmFzZT4gewpwdWJsaWM6CglTbWFydFB0cihEZXJpdmVkKiBwKSA6IHBvaW50ZWUoc3RhdGljX2Nhc3Q8QmFzZSo+KHApKXt9CnByaXZhdGU6CiAgICBCYXNlKiBwb2ludGVlOwp9OwppbnQgbWFpbigpIHsKICAgIFNtYXJ0UHRyPERlcml2ZWQ+IGQobmV3IERlcml2ZWQoKSk7CiAgICAvL2ZvbyhkKTsgLy9hbWJpZ3VvdXMgY2FsbC4gSG93IHRvIHJlbW92ZSBhbWJpZ3VpdHk/CiAgICBmb28oc3RhdGljX2Nhc3Q8U21hcnRQdHI8QmFzZT4+KGQpKTsgLy9kb2VzIG5vdCBjb21waWxlIGVpdGhlci4KICAgIHJldHVybiAwOwp9