Boost logo

Boost Users :

Subject: Re: [Boost-users] bad_any_cast being thrown but no idea why
From: Michael Caisse (boost_at_[hidden])
Date: 2009-10-31 18:12:47


John Yamokoski wrote:
> I have been pulling my hair out over this bug for a day or two now.
> Here's the synopsis. I have a boost::any object which is storing a
> std::string. Any test I do to check if indeed the any object is
> holding onto a std::string object verifies what I already know. For
> instance, the following function always returns true for my boost::any
> object:
>
> bool is_string(const boost::any& operand)
> {
> return ( operand.type() == typeid(std::string) );
> }
>
> Also if I just print out the typeinfo information for the boost::any
> object is also shows that its holding onto a std::string:
>
> std::stringstream ss;
> ss << "any object: " << obj.type().name() << ", a string: " <<
> typeid(std::string).name();
>
> yields,
>
> any object: Ss, a string: Ss
>
> However, whenever I try and actually cast my object to a string
> (boost::any_cast<std::string>(...)), I always get
> "boost::bad_any_cast: failed conversion using boost::any_cast".
>
> Could this possibly be a compiler issue? I saw one other thread where
> "-fvisibility=hidden" was causing some problems for
> boost::program_options and std::string. In my situation, I have a
> library which is responsible for creating those boost::any objects.
> Then its in a separately compiled library where I am getting the
> problems.
> _______________________________________________
>

Hi John -

The problem is that the RTTI id's are different between your lib
and the executable. You can use the undocumented and very useful
unsafe cast:

        boost::unsafe_any_cast< std::string>( ... )

Of course, this creates a problem since it is not safe and if the
any doesn't contain a std::string there will be a surprise.

I think the typical way of handling this (or at least what I do)
is something like this:

----------------------

template< typename T > bool contains( const boost::any& a )
{
   try
   {
      // we do the comparison with 'name' because across shared library boundries we get
      // two different type_info objects
      return( std::strcmp( typeid( T ).name(), a.type().name() ) == 0 );
   }
   catch( ... )
   { }

   return false;
}

...

if( contains< std::string >( foo ) )
{
   bar = boost::unsafe_any_cast< std::string >( &foo );
}

-------------------------

Hope this helps you out.
michael

-- 
----------------------------------
Michael Caisse
Object Modeling Designs
www.objectmodelingdesigns.com

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net