[any] Is it possible to support polymorphism in boost::any?

Hello, It seems that boost::any does not support polymorphism in the following sample. class A {}; class B : public A {}; void foo( boost::any& _any ) { try { A* p = any_cast< A* >( _any ); <-- Only succeed when _any contain a pointer to a object that is exactly class A, but not any object that is descendant of class A, like B. do_some_thing( p ); } catch( const bad_any_cast& ) { } } void goo() { A* pa = new B; boost::any a = pa; foo( a ); } Is it possible to make it support this polymorphism usage? Because boost::any is a type-safe replacement of void*, I hope that boost::any has the same polymorphic behavior as void*. Regards, Tang Jiang Jun

On Mon, 6 Sep 2010 16:27:56 +0200, Tang Jiang Jun <tangjiangjun@gmail.com> wrote:
Is it possible to make it support this polymorphism usage? Because boost::any is a type-safe replacement of void*, I hope that boost::any has the same polymorphic behavior as void*.
Regards, Tang Jiang Jun
One thing to point out is that void* doesn't fully support polymorphic behavior. given: class a { public: int aa; }; class b { public: int bb; } class c: public a, public b { int cc; } ccc; int main() { void* ptr = &ccc; class a* ptr1 = (class a*)(ptr); class b* ptr2 = (class b*)(ptr); } My understanding is that the assignments to ptr1 and ptr2 are undefined behavior, and that in practice the assignment to ptr2 will normally be "wrong" in that ptr2 will not point to the b sub-object. any will just tell you that you are "breaking the rules" while void will not. Richard Damon

I agree with you that void* just support polymorphism for single inheritance. However I think maybe it is possible to make boost::any to support full polymorphic behavior, because, for boost::any, there still has accurate type information when casting happens. With some tricks, maybe we can use dynamic_cast to help boost::any to cast the internal pointer to correct child class object. Thanks! Tang Jiang Jun On Mon, Sep 6, 2010 at 5:29 PM, Richard Damon <Richard@damon-family.org>wrote:
On Mon, 6 Sep 2010 16:27:56 +0200, Tang Jiang Jun <tangjiangjun@gmail.com> wrote:
Is it possible to make it support this polymorphism usage? Because boost::any is a type-safe replacement of void*, I hope that boost::any has the same polymorphic behavior as void*.
Regards, Tang Jiang Jun
One thing to point out is that void* doesn't fully support polymorphic behavior.
given:
class a { public: int aa; };
class b { public: int bb; }
class c: public a, public b { int cc; } ccc;
int main() { void* ptr = &ccc;
class a* ptr1 = (class a*)(ptr); class b* ptr2 = (class b*)(ptr); }
My understanding is that the assignments to ptr1 and ptr2 are undefined behavior, and that in practice the assignment to ptr2 will normally be "wrong" in that ptr2 will not point to the b sub-object.
any will just tell you that you are "breaking the rules" while void will not.
Richard Damon _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

On 06/09/10 16:49, Tang Jiang Jun wrote:
I agree with you that void* just support polymorphism for single inheritance. However I think maybe it is possible to make boost::any to support full polymorphic behavior, because, for boost::any, there still has accurate type information when casting happens. With some tricks, maybe we can use dynamic_cast to help boost::any to cast the internal pointer to correct child class object.
I'd be surprised there is such a trick to do that.

On Mon, 6 Sep 2010 17:49:41 +0200, Tang Jiang Jun <tangjiangjun@gmail.com> wrote:
I agree with you that void* just support polymorphism for single inheritance. However I think maybe it is possible to make boost::any to support full polymorphic behavior, because, for boost::any, there still has accurate type information when casting happens. With some tricks, maybe we can use dynamic_cast to help boost::any to cast the internal pointer to correct child class object.
Thanks! Tang Jiang Jun
void* does NOT officially support polymorphism. If you look at the standard you can cast from T* to void* to T* (with allowed variation in const and volatile) but not from A* to void* to B*, even if there is a inheritance relationship between A and B. It may work for many platforms (for single inheritance), but officially it is Undefined Behavior. Richard Damon

I had exactly the same problem with some code of mine. The code was a factory like this typedef Factory<std::function<boost::any ()> > Factory_t; I wanted to store objects derived from a class (in this case, but I also wanted to support types not rooted in the same object hierarchy) and I was surprised that it failed. I think the right thing would do to work under these assumptions as well. 2010/9/6 Tang Jiang Jun <tangjiangjun@gmail.com>:
Hello, It seems that boost::any does not support polymorphism in the following sample. class A {}; class B : public A {}; void foo( boost::any& _any ) { try { A* p = any_cast< A* >( _any ); <-- Only succeed when _any contain a pointer to a object that is exactly class A, but not any object that is descendant of class A, like B. do_some_thing( p ); } catch( const bad_any_cast& ) { } } void goo() { A* pa = new B; boost::any a = pa; foo( a ); } Is it possible to make it support this polymorphism usage? Because boost::any is a type-safe replacement of void*, I hope that boost::any has the same polymorphic behavior as void*. Regards, Tang Jiang Jun
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

After thinking deeper, I figure out a rough implementation for this idea, and prove it can work with polymorphism. (It is just rough concept verification, and need a lot of work to polish it and make it usable). 1. Add a build method that accept base class info, template<typename ValueType, typename BaseType1, typename BaseType2> static any create( ValueType* value) { any a; a.content = new holder<ValueType, BaseType1, BaseType2>(value); return a; } 2. Add a interface to placeholder to convert held to base class pointer, virtual void* get_converted_pointer( const std::type_info& _typeinfo ) const = 0; 3. Pass base class info to concrete holder and implement previous interface, template<typename ValueType, typename BaseType1, typename BaseType2> class holder : public placeholder virtual void* get_converted_pointer( const std::type_info& _typeinfo ) const { if( _typeinfo == typeid( ValueType ) || _typeinfo == typeid( BaseType1 ) ) { return held; } else if( _typeinfo == typeid( BaseType2 ) ) { return static_cast< BaseType2* >( held ); } else { return 0; } } 4. Modify any_cast to use this interface, template<typename ValueType> ValueType * any_cast(any * operand) { if( !operand ) return 0; return (ValueType*)operand->content->get_converted_pointer( typeid(ValueType) ); } 5. After that we can use boost:any as a type-safe and polymorphic variant pointer. Here is the sample. struct A { A( int _a = 0 ) : a( _a ) {} int a; }; struct B { B( int _b = 0 ) : b( _b ) {} int b; }; struct C : public A, public B { C( int _a = 0, int _b = 0, int _c = 0 ) : A( _a ), B( _b ), c( _c ) {} int c; }; void afoo( any& _any ) { A* pa = any_cast< A >( &_any ); if( pa ) { cout << "A - " << pa->a << endl; } } void bfoo( any& _any ) { B* pb = any_cast< B >( &_any ); if( pb ) { cout << "B - " << pb->b << endl; } } int _tmain(int argc, _TCHAR* argv[]) { any a = any::create< C, A, B>( new C( 1, 2, 3 ) ); afoo( a ); bfoo( a ); return 0; } On Tue, Sep 7, 2010 at 12:31 AM, Germán Diago <germandiago@gmail.com> wrote:
I had exactly the same problem with some code of mine.
The code was a factory like this
typedef Factory<std::function<boost::any ()> > Factory_t;
I wanted to store objects derived from a class (in this case, but I also wanted to support types not rooted in the same object hierarchy) and I was surprised that it failed. I think the right thing would do to work under these assumptions as well.
2010/9/6 Tang Jiang Jun <tangjiangjun@gmail.com>:
Hello, It seems that boost::any does not support polymorphism in the following sample. class A {}; class B : public A {}; void foo( boost::any& _any ) { try { A* p = any_cast< A* >( _any ); <-- Only succeed when _any contain a pointer to a object that is exactly class A, but not any object that is descendant of class A, like B. do_some_thing( p ); } catch( const bad_any_cast& ) { } } void goo() { A* pa = new B; boost::any a = pa; foo( a ); } Is it possible to make it support this polymorphism usage? Because boost::any is a type-safe replacement of void*, I hope that boost::any has the same polymorphic behavior as void*. Regards, Tang Jiang Jun
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

AMDG Tang Jiang Jun wrote:
After thinking deeper, I figure out a rough implementation for this idea, and prove it can work with polymorphism. (It is just rough concept verification, and need a lot of work to polish it and make it usable).
A more automated way would be to use multiple inheritance and cross cast. class any_impl_base { public: virtual ~any_impl_base() {} }; template<class T, bool is_class = boost::is_class<T>::value> class any_impl : public T, public any_impl_base {}; In Christ, Steven Watanabe

That's an excellent idea! It's so concise and delicate to use different internal holders to represent different sub-objects. However I have a question about the query. How should a any object find which holder is the correct one to the casting query for one special base class? Thanks! On Mon, Sep 6, 2010 at 9:05 PM, Steven Watanabe <watanabesj@gmail.com>wrote:
AMDG
Tang Jiang Jun wrote:
After thinking deeper, I figure out a rough implementation for this idea, and prove it can work with polymorphism. (It is just rough concept verification, and need a lot of work to polish it and make it usable).
A more automated way would be to use multiple inheritance and cross cast.
class any_impl_base { public: virtual ~any_impl_base() {} };
template<class T, bool is_class = boost::is_class<T>::value> class any_impl : public T, public any_impl_base {};
In Christ, Steven Watanabe
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

This feature is a must! 2010/9/7 Tang Jiang Jun <tangjiangjun@gmail.com>:
That's an excellent idea! It's so concise and delicate to use different internal holders to represent different sub-objects. However I have a question about the query. How should a any object find which holder is the correct one to the casting query for one special base class? Thanks!
On Mon, Sep 6, 2010 at 9:05 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Tang Jiang Jun wrote:
After thinking deeper, I figure out a rough implementation for this idea, and prove it can work with polymorphism. (It is just rough concept verification, and need a lot of work to polish it and make it usable).
A more automated way would be to use multiple inheritance and cross cast.
class any_impl_base { public: virtual ~any_impl_base() {} };
template<class T, bool is_class = boost::is_class<T>::value> class any_impl : public T, public any_impl_base {};
In Christ, Steven Watanabe
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (5)
-
Germán Diago
-
Mathias Gaunard
-
Richard Damon
-
Steven Watanabe
-
Tang Jiang Jun