Opened 16 years ago

Last modified 13 years ago

#754 closed Bugs (fixed)

boost::any - typeid comparison across shared boundaries — at Initial Version

Reported by: kulik Owned by: alnsn
Milestone: Component: any
Version: None Severity: Problem
Keywords: Cc:

Description

typeid comparison (using == operator) fails under
certain platforms and certain conditions. For me it
fails for template classes at least (std::vector for
example) when I use it across shared boundaries.
Therefore boost::any doesn't work in these cases and
throws bad_any_cast exception even when it returns it
holds the same type I am about to cast it to (I am
using gcc-4.1).

boost::python has already solved this by comparing
string representations of types under problematic
platforms. This works well in all cases but can be a
bit slower.

In boost/python/type_id.hpp:
// for this compiler at least, cross-shared-library
type_info
// comparisons don't work, so use typeid(x).name()
instead. It's not
// yet clear what the best default strategy is.
# if (defined(__GNUC__) && __GNUC__ >= 3) \
 || defined(_AIX) \
 || (   defined(__sgi) && defined(__host_mips)) \
 || (defined(linux) && defined(__INTEL_COMPILER) &&
defined(__ICC))
#  define BOOST_PYTHON_TYPE_ID_NAME
# endif

I would say the same thing should be applied to boost::any

In boost/any.hpp:
template<typename ValueType>
ValueType * any_cast(any * operand)
{
    return operand && operand->type() == typeid(ValueType)
    ? &static_cast<any::holder<ValueType>
*>(operand->content)->held
                : 0;
    }

should be replaced with:

template<typename ValueType>
ValueType * any_cast(any * operand)
{
# if (defined(__GNUC__) && __GNUC__ >= 3) \
 || defined(_AIX) \
 || (   defined(__sgi) && defined(__host_mips)) \
 || (defined(linux) && defined(__INTEL_COMPILER) &&
defined(__ICC))
    return operand && !strcmp( operand->type().name(),
typeid(ValueType).name()
    ? &static_cast<any::holder<ValueType>
*>(operand->content)->held
                : 0;
# else
    return operand && operand->type() == typeid(ValueType)
    ? &static_cast<any::holder<ValueType>
*>(operand->content)->held
                : 0;
# endif
}

btw: I am aware that this may cause performance drops
and it would be great if there was a switch for that or
something for people that aren't using boost::any
across shared boundaries.

Change History (0)

Note: See TracTickets for help on using tickets.