
On 04.03.2011, at 17:15, Daniel Larimer wrote:
On 3/4/11 11:05 AM, "Stewart, Robert" <Robert.Stewart@sig.com> wrote:
Daniel Larimer wrote:
Stewart, Robert escribió:
Couldn't this functionality be added to Boost.Any itself? That is, add another cast that does dynamic_cast so there's only one library but clients get a choice about how to extract values.
The change is perhaps a bit to fundamental. Here is the "effective difference".
struct any { struct holder_base{}; template<typename T> struct holder_impl<T> : holder_base { T held; }; holder_base* data; }
struct dynamic_any { struct holder_base{}; template<typename T> struct holder_impl<T> : T, virtual holder_base {}; holder_base* data; };
Hmmm. What about just adding the equivalent of dynamic_cast<U *>(&held) and dynamic_cast<U &>(held), in a new cast function template (perhaps through the aid of friendship and a private member function) called dynamic_any_cast, to the existing Boost.Any?
The problem is that you must first cast any::placeholder* to any::holder<U>* before you can access holder<U>::held.
Unfortunately, any::holder<Derived> does not inherit from any::holder<Base> so you cannot do a dynamic cast from any::placeholder to any::holder<Base> if any::placeholder is actually an instance of any::holder<Derived>.
boost::any can do a static cast because it has verified that the types are the same and thus does not need to worry about "offsets", if the types are different, then you would need a virtual template function to calculate the offset between any two types for the cast. Unfortunately, virtual template methods are not an option.
It would be possible to implement dynamic_any_cast for the existing boost::any by using compiler-specific implementation knowledge. For example, on GCC, you could access type_info::__do_upcast to do the casting. Of course, such an implementation would have to have cases for every compiler, and it might turn out to be unimplementable on some. Sebastian