
I recently ran into a problem where I wanted to retrieve the value stored in a boost::any by casting to a base class. Unfortunately, boost::any requires you cast out the exact type as that held. Boost.DynamicAny is a vairant on Boost.Any which provides more flexible dynamic casting of the underlying type. Whereas retreiving a value from Boost.Any requires that you know the exact type stored within the Any, Boost.DynamicAny allows you to dynamically cast to either a base or derived class of the held type. Boost.DynamicAny passes all of the same unit tests as Boost.Any, but additionally supports the following test: #include <boost/dynamic_any.hpp> using boost::dynamic_any_cast; struct base { int a; }; struct base1 { int a1; }; struct derived : base, base1 { int b; }; struct other {}; void test_dynamic_cast() { derived d; dynamic_any a(d); derived & ra = dynamic_any_cast<derived&>(a); base & b = dynamic_any_cast<base&>(a); base1 & b1 = dynamic_any_cast<base1&>(a); const base1 & cb1 = dynamic_any_cast<const base1&>(a); TEST_CHECK_THROW( dynamic_any_cast<other&>(a), bad_dynamic_any_cast, "dynamic_any_cast to incorrect reference type"); For scalar types, Boost.DynamicAny works just like Boost.Any. This means that it currently does not support dynamic casting of pointers stored within the any, but that should not be too hard to add. https://github.com/bytemaster/Boost.DynamicAny

Daniel Larimer escribió:
I recently ran into a problem where I wanted to retrieve the value stored in a boost::any by casting to a base class. Unfortunately, boost::any requires you cast out the exact type as that held.
Boost.DynamicAny is a vairant on Boost.Any which provides more flexible dynamic casting of the underlying type. Whereas retreiving a value from Boost.Any requires that you know the exact type stored within the Any, Boost.DynamicAny allows you to dynamically cast to either a base or derived class of the held type. Boost.DynamicAny passes all of the same unit tests as Boost.Any, but additionally supports the following test: [...]
What's the trade-off? I mean, does Boost.DynamicAny use more memory than Boost.Any, is it slower? Thank you, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo Este mensaje se dirige exclusivamente a su destinatario. Puede consultar nuestra política de envío y recepción de correo electrónico en el enlace situado más abajo. This message is intended exclusively for its addressee. We only send and receive email on the basis of the terms set out at. http://www.tid.es/ES/PAGINAS/disclaimer.aspx

joaquin@tid.es wrote:
Daniel Larimer escribió:
I recently ran into a problem where I wanted to retrieve the value stored in a boost::any by casting to a base class. Unfortunately, boost::any requires you cast out the exact type as that held.
Boost.DynamicAny is a vairant on Boost.Any which provides more flexible dynamic casting of the underlying type. Whereas retreiving a value from Boost.Any requires that you know the exact type stored within the Any, Boost.DynamicAny allows you to dynamically cast to either a base or derived class of the held type.
What's the trade-off? I mean, does Boost.DynamicAny use more memory than Boost.Any, is it slower?
I presume you mean other than the difference between static_cast and dynamic_cast? 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. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Stewart, Robert escribió:
joaquin@tid.es wrote:
Daniel Larimer escribió:
I recently ran into a problem where I wanted to retrieve the value stored in a boost::any by casting to a base class. Unfortunately, boost::any requires you cast out the exact type as that held.
Boost.DynamicAny is a vairant on Boost.Any which provides more flexible dynamic casting of the underlying type. Whereas retreiving a value from Boost.Any requires that you know the exact type stored within the Any, Boost.DynamicAny allows you to dynamically cast to either a base or derived class of the held type.
What's the trade-off? I mean, does Boost.DynamicAny use more memory than Boost.Any, is it slower?
I presume you mean other than the difference between static_cast and dynamic_cast?
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.
That is exactly my point. Joaquín M López Muñoz Telefóinca, Investigación y Desarrollo Este mensaje se dirige exclusivamente a su destinatario. Puede consultar nuestra política de envío y recepción de correo electrónico en el enlace situado más abajo. This message is intended exclusively for its addressee. We only send and receive email on the basis of the terms set out at. http://www.tid.es/ES/PAGINAS/disclaimer.aspx

On 3/4/11 6:46 AM, "joaquin@tid.es" <joaquin@tid.es> wrote:
Stewart, Robert escribió:
joaquin@tid.es wrote:
Daniel Larimer escribió:
I recently ran into a problem where I wanted to retrieve the value stored in a boost::any by casting to a base class. Unfortunately, boost::any requires you cast out the exact type as that held.
Boost.DynamicAny is a vairant on Boost.Any which provides more flexible dynamic casting of the underlying type. Whereas retreiving a value from Boost.Any requires that you know the exact type stored within the Any, Boost.DynamicAny allows you to dynamically cast to either a base or derived class of the held type. I misspoke, you cannot cast to a more-derived type than that held..
What's the trade-off? I mean, does Boost.DynamicAny use more memory than Boost.Any, is it slower?
Memory usage should be the same, compile times may increase slightly as a helper template was needed to separate the scalar vs non-scalar implementation. Runtime dynamic cast performance will be slower than the compile time static cast in boost::any. Static cast is still used for scalar types.
I presume you mean other than the difference between static_cast and dynamic_cast?
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; }; With the extra layer of inheritance, there is some potential for conflicts with the clone() and type() virtual methods provided by holder_impl<> and any method of the same name provided by T. These conflicts could be mitigated by changing the name to __dynamic_any__clone() /type(). I had assumed there was a solid design rational for using aggregation vs inheritance in boost::any and it is probably related to it having less restrictions on the type that can be held. In my original email I thought it would be easy to add support for casting dynamic_any(derived*) to dynamic_any(base*), but because I cannot inherit from a pointer, I have no way to get the RTTI info required to know that derived inherits base or what the offset is. If anyone has a way to polymorphically determine whether base* is inherited by derived* and if so perform the proper pointer offsets to do a cast let me know.
That is exactly my point.
Joaquín M López Muñoz Telefóinca, Investigación y Desarrollo
Este mensaje se dirige exclusivamente a su destinatario. Puede consultar nuestra política de envío y recepción de correo electrónico en el enlace situado más abajo. This message is intended exclusively for its addressee. We only send and receive email on the basis of the terms set out at. http://www.tid.es/ES/PAGINAS/disclaimer.aspx _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

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? _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

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.
_____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com
IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

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

On 3/4/2011 5:36 PM, Sebastian Redl wrote:
On 04.03.2011, at 17:15, Daniel Larimer wrote:
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.
Maybe the traits I suggested long time ago could solve this problem in some variant. http://www.comeaucomputing.com/iso/lwg-active.html#849 That is, if we could determine a suitable root class with a virtual function, we could simply instantiate holder<root*>. (this would also generate less code). Wold not work if there is no unique base class I guess; -Thorsten

Daniel Larimer wrote:
I recently ran into a problem where I wanted to retrieve the value stored in a boost::any by casting to a base class. Unfortunately, boost::any requires you cast out the exact type as that held. Boost.DynamicAny is a vairant on Boost.Any which provides more flexible dynamic casting of the underlying type. Whereas retreiving a value from Boost.Any requires that you know the exact type stored within the Any, Boost.DynamicAny allows you to dynamically cast to either a base or derived class of the held type.
I don't see how you can cast to "derived class of the held type" because holder<T> always stores a (sliced) copy of an object you passed to a constructor. Your test casts either to base classes or to the same type. We discussed this feature several years ago but for some reason I didn't commit it. Take a look at this: http://cpp-experiment.cvs.sourceforge.net/viewvc/cpp-experiment/dynamic_any/boost/dynamic_any/any.hpp?revision=1.49&view=markup Alex
Boost.DynamicAny is a vairant on Boost.Any which provides more flexible dynamic casting of the underlying type. Whereas retreiving a value from Boost.Any requires that you know the exact type stored within the Any, Boost.DynamicAny allows you to dynamically cast to either a base or derived class of the held type. Boost.DynamicAny passes all of the same unit tests as Boost.Any, but additionally supports the following test:
#include <boost/dynamic_any.hpp>
using boost::dynamic_any_cast; struct base { int a; };
struct base1 { int a1; };
struct derived : base, base1 { int b; };
struct other {};
void test_dynamic_cast() { derived d; dynamic_any a(d); derived & ra = dynamic_any_cast<derived&>(a); base & b = dynamic_any_cast<base&>(a); base1 & b1 = dynamic_any_cast<base1&>(a); const base1 & cb1 = dynamic_any_cast<const base1&>(a);
TEST_CHECK_THROW( dynamic_any_cast<other&>(a), bad_dynamic_any_cast, "dynamic_any_cast to incorrect reference type");
For scalar types, Boost.DynamicAny works just like Boost.Any. This means that it currently does not support dynamic casting of pointers stored within the any, but that should not be too hard to add.
https://github.com/bytemaster/Boost.DynamicAny _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
--
participants (6)
-
Alexander Nasonov
-
Daniel Larimer
-
joaquin@tid.es
-
Sebastian Redl
-
Stewart, Robert
-
Thorsten Ottosen