[ Date Prev][ Date Next][ Thread Prev][ Thread Next][ Date Index][ Thread Index]
Re: [cxx-abi-dev] trivial __dynamic_cast fails?
- To: David Baraff <deb@xxxxxxxxx>
- Subject: Re: [cxx-abi-dev] trivial __dynamic_cast fails?
- From: David Abrahams <dave@xxxxxxxxxxxxxxxxxxxx>
- Date: Fri, 27 Feb 2004 19:20:09 -0500
David Baraff <deb@xxxxxxxxx> writes:
>> From: Daveed Vandevoorde <daveed@xxxxxxx>
>
> Please note that Mark Mitchell already pointed me in the right
> direction, though it shifts a lot of implementation burden to me. I
> can use the base_type_info to compute the address shift as I chain
> upward from derived to base, which is all I'm really after in this
> case.
Could you please outline the details?
>> There has been occasional talk among WG21/
>> J16 actives about adding a facility like
>> what David B. is looking for, but so far
>> no concrete proposals. I'm going to CC
>> David Abrahams who mentioned the desire
>> for this once. Perhaps he has some insight
>> into how widespread the need for this is.
>
> Here's a biggy. Consider the boost::any class. Currently, if it
> holds a Derived* and you ask it for a Base*, I think it says "no can
> do." Imagine if it could actually say "yes, I can give you back a
> Base*", because it could dynamically look up the parent chain, and do
> the address shift.
>
> That would make boost::any a heck of a lot more useful than it is today.
boost::any could already be modified to do this, since it "knows" the
"Derived" type. I've enclosed an implementation. Seems to reveal EH
bugs in quite a few compilers, tho ;-)
// See http://www.boost.org/libs/any for Documentation.
#ifndef BOOST_ANY_INCLUDED
#define BOOST_ANY_INCLUDED
// what: variant type boost::any
// who: contributed by Kevlin Henney,
// with features contributed and bugs found by
// Ed Brey, Mark Rodgers, Peter Dimov, and James Curran
// when: July 2001
// where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95
#include <algorithm>
#include <typeinfo>
#include "boost/config.hpp"
#include <boost/throw_exception.hpp>
namespace boost
{
class any
{
public: // structors
any()
: content(0)
{
}
template<typename ValueType>
any(const ValueType & value)
: content(new holder<ValueType>(value))
{
}
any(const any & other)
: content(other.content ? other.content->clone() : 0)
{
}
~any()
{
delete content;
}
public: // modifiers
any & swap(any & rhs)
{
std::swap(content, rhs.content);
return *this;
}
template<typename ValueType>
any & operator=(const ValueType & rhs)
{
any(rhs).swap(*this);
return *this;
}
any & operator=(const any & rhs)
{
any(rhs).swap(*this);
return *this;
}
public: // queries
bool empty() const
{
return !content;
}
const std::type_info & type() const
{
return content ? content->type() : typeid(void);
}
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
private: // types
#else
public: // types (public so any_cast can be non-friend)
#endif
class placeholder
{
public: // structors
virtual ~placeholder()
{
}
public: // queries
virtual const std::type_info & type() const = 0;
virtual placeholder * clone() const = 0;
virtual void throwme() = 0;
};
template<typename ValueType>
class holder : public placeholder
{
public: // structors
holder(const ValueType & value)
: held(value)
{
}
public: // queries
virtual const std::type_info & type() const
{
return typeid(ValueType);
}
virtual placeholder * clone() const
{
return new holder(held);
}
virtual void throwme()
{
ValueType* me = &held;
throw me;
}
public: // representation
ValueType held;
};
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
private: // representation
template<typename ValueType>
friend ValueType * any_cast(any *);
#else
public: // representation (public so any_cast can be non-friend)
#endif
placeholder * content;
};
class bad_any_cast : public std::bad_cast
{
public:
virtual const char * what() const throw()
{
return "boost::bad_any_cast: "
"failed conversion using boost::any_cast";
}
};
template<typename ValueType>
ValueType * any_cast(any * operand)
{
if (0 && operand && operand->type() == typeid(ValueType))
{
return &static_cast<any::holder<ValueType> *>(operand->content)->held;
}
else try
{
operand->content->throwme();
}
catch(ValueType* x)
{
return const_cast<ValueType*>(x);
}
catch(...) { }
return 0;
}
template<typename ValueType>
const ValueType * any_cast(const any * operand)
{
return any_cast<ValueType>(const_cast<any *>(operand));
}
template<typename ValueType>
ValueType any_cast(const any & operand)
{
const ValueType * result = any_cast<ValueType>(&operand);
if(!result)
boost::throw_exception(bad_any_cast());
return *result;
}
}
// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
//
// Permission to use, copy, modify, and distribute this software for any
// purpose is hereby granted without fee, provided that this copyright and
// permissions notice appear in all copies and derivatives.
//
// This software is provided "as is" without express or implied warranty.
#endif
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
|