1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <map>
#include <iostream>
#include <typeinfo.h>
//conversion du parametre de type BASE_CLASS_TYPE vers CLASS_TYPE
template<class CLASS_TYPE, class BASE_CLASS_TYPE, class VISITOR_TYPE>
void call(void (*f)( VISITOR_TYPE &, CLASS_TYPE & ), VISITOR_TYPE & visitor, BASE_CLASS_TYPE & obj)
{
f(visitor, static_cast<CLASS_TYPE&>(obj));
}
//modification du prototype de la fonction de visitation de void(VISITOR_TYPE&, BASE_CLASS_TYPE&) vers void(VISITOR_TYPE&, CLASS_TYPE&)
template<class CLASS_TYPE, class BASE_CLASS_TYPE, class VISITOR_TYPE>
boost::function<void(VISITOR_TYPE &, BASE_CLASS_TYPE &)> bind_function(void (*f)(VISITOR_TYPE &, CLASS_TYPE & ))
{
return boost::function<void(VISITOR_TYPE &, BASE_CLASS_TYPE &)>( boost::bind( call<CLASS_TYPE,BASE_CLASS_TYPE,VISITOR_TYPE>, f, _1 , _2) );
}
//map static de const type_info* vers boost::function<void(VISITOR_TYPE &,BASE_CLASS_TYPE &)
template< class VISITOR_TYPE, class BASE_CLASS_TYPE>
static std::map<const type_info*,boost::function<void(VISITOR_TYPE &,BASE_CLASS_TYPE &)>> & functions()
{
static std::map<const type_info*,boost::function<void(VISITOR_TYPE &,BASE_CLASS_TYPE &)>> static_map;
return static_map;
}
//Le visiteur de base
template<class VISITOR_TYPE, class BASE_CLASS_TYPE>
class BaseVisitor
{
public:
typedef boost::function<void(VISITOR_TYPE &,BASE_CLASS_TYPE &)> function_type;
//enregistrement d'une fonction de visitation
template< class CLASS_TYPE >
static void Register(void (*fn)(VISITOR_TYPE & ,CLASS_TYPE & ) )
{
functions<VISITOR_TYPE,BASE_CLASS_TYPE>()[&typeid(CLASS_TYPE)] = bind_function<CLASS_TYPE,BASE_CLASS_TYPE,VISITOR_TYPE>(fn);
}
//renvoie la fonction de visitation, pas indispensable
template< class CLASS_TYPE >
static function_type GetFunction()
{
std::map<const type_info*,function_type>::iterator it = functions<VISITOR_TYPE,BASE_CLASS_TYPE>().find(&typeid(CLASS_TYPE));
if(it != functions<VISITOR_TYPE,BASE_CLASS_TYPE>().end())
return it->second;
else
return function_type();
}
//Visite un objet
virtual void Visit(BASE_CLASS_TYPE & obj)
{
std::map<const type_info*,function_type>::iterator it = functions<VISITOR_TYPE,BASE_CLASS_TYPE>().find(&typeid(obj));
if(it != functions<VISITOR_TYPE,BASE_CLASS_TYPE>().end())
it->second(static_cast<VISITOR_TYPE&>(*this),obj);
else
DefaultBehavior(obj);
}
//Comportement par default pour les classes qui ne sont pas enregistrées
virtual void DefaultBehavior(BASE_CLASS_TYPE & )
{}
};
//Hiérarchie de classe bidon, avec fonction virtuelle obligatoire pour l'utilisation du RTTI
struct A{
int virtual get(){return 0;}
};
struct B : public A{
};
struct C : public A{};
//Un visiteur quelconque
class visitor : public BaseVisitor<visitor,A>
{};
//Les fonctions de visitation
void testA(visitor & v, A & a)
{
std::cout<<"A"<<std::endl;
}
void testB(visitor & v, B & b)
{
std::cout<<"B"<<std::endl;
}
void testC(visitor & v, C & b)
{
std::cout<<"C"<<std::endl;
}
int main()
{
A *a=new A;
A *b=new B;
C *c=new C;
//enregistrement des fonctions
visitor::Register(&testA);
visitor::Register(&testB);
visitor v;
v.Visit(*a);
v.Visit(*b);
v.Visit(*c);
std::system("pause");
} |
Partager