tags:

views:

717

answers:

2

I want boost::any_cast<T> to only throw an exception when the type of the any doesn't have an implicit conversion to T. The normal behaviour seems to be to throw an exception if the type of the any is not T, regardless of implicit conversions.

Example:

boost::any a = 1;
boost::any_cast<int>(a); // This succeeds, and rightfully so
boost::any_cast<long>(a); // I don't want this to throw
boost::any_cast<Widget>(a); // I want this to throw

Could anyone tell me if there's a simple way to get the functionality I want, or better yet give me a good reason for why the existing behaviour is the way it is?

+2  A: 

Well you can't do it. The any mechanism works like this:

struct base {
    virtual ~base() { }
};

template<typename T>
struct concrete_base : base {
    T t;
    concrete_base(T t):t(t) { }
};

struct my_any {
    base * b;

    template<typename T>
    my_any(T t):b(new concrete_base<T>(t)) { }

    template<typename T>
    T any_cast() { 
        concrete_base<T> * t = dynamic_cast< concrete_base<T>* >(b);
        if(!t) throw bad_any_cast();
        return t->t;
    }
};

I hope it's clear what the above does. There is no way you could do what you are looking for i think. The reason is that there is no information about the type kept that could prove useful here. RTTI doesn't provide it.

Johannes Schaub - litb
A: 

Crystal clear, thanks.

If what I read in Meyers' 'Effective C++' is correct, c++0x will introduce type traits that will allow you to check whether an implicit conversion between two types is available; presumably that could be used to achieve what I want?

But that's a way off, I'll just make do with the current behaviour for now! Thanks again!

Ben Hymers
well. it will still not work. checking whether U is convertible to T is already possible today. The problem is that you cannot retrieve T in the first place. You can only check whether a T is stored using any_cast.
Johannes Schaub - litb