
Hello all, Is there any visitor mechanism somewhere in boost that allows one to introspect the contained type of a boost::any? I've been using boost::variant frequently and I love the way its visitor works, but it's not always practical to know all possible types at compile time (library dependencies, compilation time etc..). I thought something similiar for boost::any, and I put together a small test: any_variant<T0, T1, T2> any_of_type_T0_T1_T2; It allows visitation of the types given as template parameters. A trivial example would be struct print_visitor { template<class T> void operator()(const T& x) const { std::cout << x <<std::endl; } }; void test() { typedef any_variant<int, float, std::string> any_types; boost::any a; any_types v(a); a = (int) 35; v(print_visitor()); a = std::string("str"); v(print_visitor()); a = (double) 45.0; v(print_visitor()); } // prints 35 str Also the example from boost::any docs, class consumer { public: virtual void notify(const any &) = 0; ... }; could be implemented like class my_consumer : public consumer { virtual void notify(const any &a) { any_variant<msg0, msg1> av(a); av(*this); } void operator()(const msg0&); void operator()(const msg1&); } The implementation is very basic, it just iterates over the types and compares typeids. If a match is found it calls the visitor and returns true, otherwise false. Does anyone else have a use for this, or have another solution at hand? Best regards, Christian #include <boost/any.hpp> #include <boost/mpl/begin.hpp> #include <boost/mpl/end.hpp> #include <boost/mpl/deref.hpp> #include <boost/mpl/vector.hpp> #include <boost/preprocessor/cat.hpp> #include <boost/preprocessor/control/expr_if.hpp> #include <boost/preprocessor/repetition/enum.hpp> #include <boost/preprocessor/repetition/enum_params.hpp> namespace detail { template<bool done = true> struct typeitr_loop { template<typename Iterator, typename LastIterator, typename Visitor> static bool invoke(boost::any&, Visitor) { return false; } }; template<> struct typeitr_loop<false> { template<typename Iterator, typename Last, typename Visitor> static bool invoke(boost::any& a, Visitor v) { typedef boost::mpl::deref<Iterator>::type type; if(typeid(type) == a.type()) { v(*boost::unsafe_any_cast<type>(&a)); return true; } else { typedef boost::mpl::next<Iterator>::type itr; return typeitr_loop<boost::is_same<itr, Last>::value>::invoke <itr, Last>(a, v); } } }; template<class Types, class Visitor> inline bool visit_any_type(boost::any& a, Visitor f) { typedef typename boost::mpl::begin<Types>::type first; typedef typename boost::mpl::end<Types>::type last; return detail::typeitr_loop<boost::is_same<first, last>::value>::invoke <first, last>(a, f); } } // // Preprocessor code copied from <boost/multi_index/indexed_by.hpp> // #ifndef ANY_VISITOR_LIMIT_TYPES #define ANY_VISITOR_LIMIT_TYPES 10 #endif #define ANY_VISITOR_TEMPLATE_PARM(z,n,var) \ typename BOOST_PP_CAT(var,n) BOOST_PP_EXPR_IF(n,=boost::mpl::na) template < BOOST_PP_ENUM( ANY_VISITOR_LIMIT_TYPES, ANY_VISITOR_TEMPLATE_PARM,T)
class any_variant { boost::any& any_; public: typedef boost::mpl::vector<BOOST_PP_ENUM_PARAMS(ANY_VISITOR_LIMIT_TYPES,T)> types; any_variant(boost::any& a) : any_(a) {} typedef bool result_type; template<class Visitor> bool operator()(Visitor v) const { return detail::visit_any_type<types>(any_, v); } }; #undef ANY_VISITOR_TEMPLATE_PARM #undef ANY_VISITOR_LIMIT_TYPES