struct Base {
virtual Base* do_something() = 0;
};
struct Derived : public Base {
Derived* do_something() { return this; }
};
But as per usual, this particular feature wasn't properly thought through. After all, what if I need to use an owning pointer? Only raw pointers are co-variant.
struct Base {
virtual std::unique_ptr<Base> do_something() = 0;
};
struct Derived : public Base {
virtual std::unique_ptr<Derived> do_something() {
return std::unique_ptr<Derived>(new Derived(*this));
}
};
Oops - not allowed. What, are my UDTs second class citizens now? I think that this rule should be widened to allow any implicit conversion, especially now that we have explicit conversion operators in C++0x.
There are other examples of this problem.
template<typename T, typename U> void CheckType(T* t) {
if (!dynamic_cast<U*>(t)) {
// Whoops
}
}
Ok- for raw pointers. But, of course, we can't do that for
shared_ptr
, so it's time to overload.template<typename T, typename U> void CheckType(std::shared_ptr<T> t) {
if(!std::dynamic_pointer_cast<U*>(t)) {
// Whoops
}
}
Of course, unique_ptr doesn't even provide such a facility, so we'll have to come up with something else- probably using get().
template<typename T, typename U> void CheckType(const std::unique_ptr<T> t) {
if (!dynamic_cast<U*>(t.get())) {
// Whoops
}
}
I sure hope that I don't have more than a couple smart pointer types, or I'm gonna be here all day. Just let me overload
dynamic_cast
and be done with it. Why bother allowing us to overload only some pointer operations? This would also allow much more natural syntax for libraries that implemented their own- like QueryInterface()
in COM, and LLVM has one and I think that Qt also has one. Some newer COM interfaces come with a nice template wrapper on QueryInterface()
that takes away some of the headache, but it's still not the same as actually supporting dynamic_cast
and being generic.
No comments:
Post a Comment