#ifndef VISITOR_H_ #define VISITOR_H_ #include "boost/type_traits/is_base_and_derived.hpp" #include "boost/type_traits/add_reference.hpp" #include "boost/type_traits/add_pointer.hpp" #include "boost/mpl/list.hpp" #include "boost/mpl/pop_front.hpp" #include "boost/mpl/front.hpp" #include "boost/mpl/apply_if.hpp" #include "boost/mpl/erase.hpp" #include "boost/mpl/find.hpp" namespace mpl = boost::mpl; /* FindDerivedHelper - This class is responsible for finding the most or least derived class in TypeList. if least is true, it finds the least derived, if least is false, the most derived. Type is the type currently under examination. */ template < bool least, class Type, class TypeList > struct FindDerivedHelper { enum { value = boost::is_base_and_derived::type>::value }; typedef typename mpl::apply_if_c::type >, FindDerivedHelper::type, typename mpl::pop_front::type > >::type type; }; /* FindDerivedHelper specialization. When the null_node is reached, then Type is the result */ template< bool least, class Type > struct FindDerivedHelper { typedef Type type; }; /* FindDerived - uses FindDerivedHelper to find the most or least derived class in TypeList */ template < bool least, class TypeList > struct FindDerived { typedef typename FindDerivedHelper< least, typename mpl::front< TypeList >::type, typename mpl::pop_front< TypeList >::type >::type type; }; /* FindMostDerived - finds the most derived class in TypeList */ template< class TypeList > struct FindMostDerived : public FindDerived {}; /* FindLeastDerived - finds the least derived class in TypeList */ template< class TypeList > struct FindLeastDerived : public FindDerived {}; template< class T > struct DefaultConvertPolicy { }; /* DefaultConvertPolicy - converts from a T* to a T* using dynamic_cast */ template struct DefaultConvertPolicy< T* > { template To Convert( const typename boost::add_reference::type f, bool& success ) { To t = dynamic_cast( f ); success = t; return t; } }; /* DefaultConvertPolicy - converts from a T& to a T& using dynamic_cast */ template struct DefaultConvertPolicy< T& > { template To Convert( const typename boost::add_reference::type f, bool& success ) { To t = dynamic_cast( f ); success = true; return t; } }; /* Visitor - TypeList - a list of classes to visit B - the base class to use PointerPolicy - a template class such that PointerPolicy::type will be the type of pointer/reference that should be used ConvertPolicy - a class that provides teh Convert template function */ template< class TypeList, class B = typename FindLeastDerived::type, template class PointerPolicy = boost::add_pointer, class ConvertPolicy = DefaultConvertPolicy< typename PointerPolicy::type > > class Visitor { typedef typename FindMostDerived::type TypeToTry; typedef typename mpl::find::type TypeToTryIter; typedef typename mpl::erase::type NextList; typedef B BaseClass; typedef typename PointerPolicy::type BaseClassPtr; typedef typename PointerPolicy::type TypeToTryPtr; public: template< class FunctionType > static void visit( BaseClassPtr bc, FunctionType func ) { ConvertPolicy cvt; bool success = false; try { // try to convert to the TypeToTry type TypeToTryPtr try_it = cvt.template Convert( bc, success ); if( success ) { // conversion was successful...do the function and end recursion func( try_it ); } } catch( ... ) { success = false; } if( !success ) { // conversion was not successful...recurse with a smaller list Visitor< NextList, B, PointerPolicy, ConvertPolicy >::visit( bc, func ); } } }; /* Visitor< mpl::null_node ...> end the recursion and do nothing if the list is empty */ template< class B, template class PointerPolicy, class ConvertPolicy> class Visitor< mpl::null_node, B, PointerPolicy, ConvertPolicy > { private: typedef B BaseClass; typedef typename PointerPolicy::type BaseClassPtr; public: template< class FunctionType > static void visit( BaseClassPtr bc, FunctionType func ) {} }; #endif