tags:

views:

100

answers:

3

May I know is there any way to determine parent class from boost::any?

#include <iostream>
#include <boost/any.hpp>

class a {
public:
    virtual ~a() {}
};

class b : public a {
};

bool is_class_a(const boost::any& any)
{
    return boost::any_cast<a>(&any) != 0;
}

bool is_class_a_v2(const boost::any& any)
{
    try
    {
        boost::any_cast<a>(any);
        return true;
    }
    catch(const boost::bad_any_cast &)
    {
        return false;
    }
}

int main()
{
    std::cout<< is_class_a(b())<< std::endl;    // return 0. but i wish to return 1.
    std::cout<< is_class_a(a())<< std::endl;    // return 1.

    std::cout<< is_class_a_v2(b())<< std::endl; // return 0. but i wish to return 1.
    std::cout<< is_class_a_v2(a())<< std::endl; // return 1.
}
+2  A: 

boost::any was designed so that it holds strongly informational objects for which identity is not significant. If you want to work with polymorphic types then you could use pointers to base class or boost::shared_ptr with base class instead of boost::any.

Kirill V. Lyadvinsky
Indeed, `boost::any` means that you'll have to know the exact type of the stored value, polymoprhism is generally used so you wouldn't need to know the exact type. In this case, it means your tests would have try any_cast to all derivated classes of `a`, but it is somewhat counterproductive.
UncleBens
A: 

Here's why it doesn't work: any_cast is a template. boost::any uses "type erasure" which means the actual type is hidden behind some kind of type-neutral abstract interface. The only informations the any_cast implementation has available is a void* pointer and the type_info object. But there is no dynamic_cast operator that supports casting in this case. So any_cast<T> just compares the type_info object of the stored object with typeid(T) and if they match it reinterpret_casts the void* pointer.

If you want to use polymorphism you should use some other wrapper class than boost::any (perhaps something like a "clone_ptr", "shared_ptr", or your own wrapper dedicated to this base class of yours).

sellibitze
A: 
struct a {
  virtual ~a() {}

  template<typename T>
  inline static bool is_subclass( T const & x) { 
    return dynamic_cast<a const *>( &x ) != NULL ; 
  }

};

struct b : public a {
};
struct c { virtual ~c() {} } ;

int main() {
  a x ; b y; c z ;
  std::cout << a::is_subclass(x) << std::endl;
  std::cout << a::is_subclass(y) << std::endl;
  std::cout << a::is_subclass(z) << std::endl;
  return 0 ;
}

Note that dynamic_cast requires polymorphic types to work.

Eld
Not related to question. I am talking on boost::any.
Yan Cheng CHEOK