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;
}
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