Actions

icon Post
text/html Subscribe
text/html Unsubscribe

[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