I propose the ability for the user to overload the dynamic_cast operator. There are two main use cases in the language right now:
Firstly, smart pointers. They can mimic the interface of raw pointers almost exactly, but not in this regard. It also makes treating smart pointers uniformly impossible, as each vendor has to introduce their own pseudo-dynamic-cast.
Secondly, many existing systems, such as LLVM and ICU, currently implement their own dynamic_cast, essentially, for their own types and classes. Being able to overload dynamic_cast would enable a consistent interface for these customised systems, as they can simply delegate the implementation.
Finally, unlike other operators, this would effectively involve overloading the primitive operator on a primitive type (pointers) for some cases.
template<typename T> class shared_ptr {
...
template<typename U> shared_ptr<typename std::remove_pointer<U>::type> operator dynamic_cast() {
return std::dynamic_pointer_cast<typename std::remove_pointer<U>::type>(*this);
}
};
Here, the shared_ptr's operator is called when attempting to cast it, such as
int main() {
std::shared_ptr<X> x;
auto y = dynamic_cast<Y*>(x);
}
Here, if anyone (probably just the implementation) wishes to have the primitive semantics of dynamic_cast, they can simply take the address of x. Also notice that unlike std::dynamic_pointer_cast, the template argument is of the same form as the argument to the primitive operator.
class Value {
...
template<typename Other> Other operator dynamic_cast(llvmFunction* p) {
return llvm::dyn_cast<typename std::remove_pointer<Other>::type>(this);
}
};
When the argument to dynamic_cast is a pointer, then the custom dynamic_cast operator is invoked on pointers or references of this type, hiding the primitive operator. In this case, it is assumed that the custom functionality essentially replaces the primitive operator's implementation, rather than extends its' interface as in shared_ptr. I don't propose a means to retrieve the original operator's behaviour in this case.
int main() {
Value* p = ...;
auto constant = dynamic_cast<Constant*>(p); // Calls overloaded operator.
}
I think that, given the prevalence of both user-defined pointer-imitating types, and home-rolled RTTI replacements, it is worth a further extension of flexibility as to how the language operates on pointers.
Feedback plix.