
On Mar 10, 2006, at 2:41 PM, Scott Meyers wrote:
It took me a little while to figure out that get<T> on a variant is really just the moral equivalent of dynamic_cast<T> with a funny syntax. I'd like to understand why, given a variant v, this syntax is used
T* p = get<T>(&v); T& r = get<T>(v);
instead of this:
T* p = variant_cast<T*>(&v); T& r = variant_cast<T&>(v); [snip] Maybe there are problems to these approaches -- I've hardly investigated them. But I would be interested to know if there is a good reason for the syntaxes for dynamic_cast, any_cast, and get to vary so much.
I think the answer is more archeological than technical :) We can't overload dynamic_cast, which is too bad: that's the right name for this sort of thing. If only someone would go ahead and write the C++0x proposal to add overloading of the cast operators, smart pointers, any, variant, python::object, and many other classes would get much more intuitive syntax. But I digress... any_cast() came around first. It probably should have had the syntax "T* p = any_cast<T*>(&a)" that you suggest. Kevlin may even have thought of that, but any and any_cast came into Boost back in the dark days when MSVC 6.0 dominated the C++ world. That means no remove_reference, no remove_pointer; I'm speculating here, but it wouldn't be the first time that the lack of suitable compilers forced Boost libraries into a suboptimal syntax. Only Kevlin would know for sure. get() came along later, when we realized that multiple types, including variant, python objects, and other dynamically-typed entities, have the same "extract as the static type T" semantics. It was built mainly to mimic any_cast, but work with a variety of types, not all of which were named "variant" (so, no "variant_cast"). In an ideal world, I think we'd end up using "dynamic_cast" for everything. Instead, we use the name "get", and I think the "any_cast<T>(&a)" is probably a holdover from the dark days that we should change. Doug