#include #include "stl_vector.h" //======================================================================================== /*********************** components_test 8-16 an Actor is a bag of components a Component implements various interfaces which defines what it can do. The goal : you want to do an operation on Actor, applied to all components which implement that operation. This is a huge success!! NOTEZ : the need to pass in a pointer to null is an artifact of MSVC6 ; it can be replaced with the more elegant Get() on any better compiler. ***************************/ //======================================================================================== class Component { public: virtual ~Component() { } }; //======================================================================================== class Actor { public: typedef std::vector ComponentVec; template std::vector GetVec( Interface * pI ) { std::vector ret; ComponentVec::iterator it; for(it = components.begin();it != components.end();++it) { Interface * pCast = dynamic_cast( *it ); if ( pCast ) ret.push_back(pCast); } return ret; } template Interface * GetFirst( Interface * pI ) { ComponentVec::iterator it; for(it = components.begin();it != components.end();++it) { Interface * pCast = dynamic_cast( *it ); if ( pCast ) return pCast; } return NULL; } template Interface * GetNext( Interface * pI ) { ComponentVec::iterator it; for(it = components.begin();it != components.end();++it) { if ( (*it) == pI ) { ++it; for(;it != components.end();++it) { Interface * pCast = dynamic_cast( *it ); if ( pCast ) return pCast; } return NULL; } } return NULL; } template int DoOnAll( Interface * pI , Function pMemFun ) { int ret = 0; ComponentVec::iterator it; for(it = components.begin();it != components.end();++it) { Interface * pCast = dynamic_cast( *it ); if ( pCast ) { (pCast->*pMemFun) (); ret++; } } return ret; } template int DoOnAll( Interface * pI , Function pMemFun , Arg1 a1 ) { int ret = 0; ComponentVec::iterator it; for(it = components.begin();it != components.end();++it) { Interface * pCast = dynamic_cast( *it ); if ( pCast ) { (pCast->*pMemFun) (a1); ret++; } } return ret; } template int DoOnAll( Interface * pI , Function pMemFun , Arg1 a1 , Arg2 a2 ) { int ret = 0; ComponentVec::iterator it; for(it = components.begin();it != components.end();++it) { Interface * pCast = dynamic_cast( *it ); if ( pCast ) { (pCast->*pMemFun) (a1,a2); ret++; } } return ret; } ~Actor() { while ( ! components.empty() ) { delete components.back(); components.pop_back(); } } //------------------------------------------------------- // data : ComponentVec components; }; //---------------------------------------------------------------------- // macro evilness : #define for_each_component( _type, _var, _container ) \ for (_type * _var = _container.GetFirst((_type *)0); \ _var != NULL; \ _var = _container.GetNext( _var ) ) //======================================================================================== class WorldComponent : public Component { public: WorldComponent(int i) { m_i = i; } void Stuff() { printf("world %d\n",m_i); } int m_i; }; class HelloComponent : public Component { public: HelloComponent(int i) { m_i = i; } void Stuff() { printf("hello %d\n",m_i); } void Stuff2(int i) { printf("hello %d %d\n",m_i,i); } void Stuff3(int i,WorldComponent * pW) { printf("hello %d %d\n",m_i,i); printf("h "); pW->Stuff(); } int m_i; }; void DoStuffH(HelloComponent * hello) { hello->Stuff(); } //======================================================================================== void components_test() { Actor a; a.components.push_back( new HelloComponent(1) ); a.components.push_back( new WorldComponent(2) ); a.components.push_back( new HelloComponent(3) ); std::vector hellos = a.GetVec( (HelloComponent *)NULL ); std::for_each(hellos.begin(),hellos.end(),DoStuffH); a.GetFirst( (WorldComponent *)NULL )->Stuff(); HelloComponent * pHello = a.GetFirst( (HelloComponent *)NULL ); pHello = a.GetNext(pHello); pHello->Stuff(); a.DoOnAll( (HelloComponent *)NULL , HelloComponent::Stuff ); a.DoOnAll( (HelloComponent *)NULL , HelloComponent::Stuff2 , 4 ); a.DoOnAll( (HelloComponent *)NULL , HelloComponent::Stuff3 , 4 , a.GetFirst( (WorldComponent *)NULL ) ); for_each_component( HelloComponent, p, a ) { p->Stuff2(99); } } //========================================================================================