boost::any visitor of known types

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

Christian, On 9/7/07, Christian Holmquist <c.holmquist@gmail.com> wrote:
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..). [snip] Does anyone else have a use for this, or have another solution at hand?
Some long time back I had added support into Boost.Any for visitation: http://boost-sandbox.cvs.sourceforge.net/boost-sandbox/boost-sandbox/boost/a... http://boost-sandbox.cvs.sourceforge.net/boost-sandbox/boost-sandbox/libs/an... Basically, the interface is as seen in the `test_dynamic_visit` test case: class my_visitor : public boost::dynamic_visitor_base, public boost::dynamic_visitor_interface<T1>, ..., public boost::dynamic_visitor_interface<TN> { ... public: /*override*/ void visit(T1&); ... /*override*/ void visit(TN&); }; and then an instance of the visitor may be passed to a boost::any: boost::any a = ...; my_visitor v; boost::apply_visitor(v, a); Of course this assumes (parts of) the Boost.Visitor library, also in the sandbox. In any case, something based on this idea might be another alternative to what you're proposing. Eric
participants (2)
-
Christian Holmquist
-
Eric Friedman