Added class template visitor_base.
This commit is contained in:
parent
619909de76
commit
85ef242fe3
1 changed files with 77 additions and 0 deletions
|
@ -20,13 +20,90 @@
|
|||
#ifndef WB_VISITOR_HPP_
|
||||
#define WB_VISITOR_HPP_
|
||||
|
||||
#include "action.hpp"
|
||||
#include "side_actions.hpp"
|
||||
#include "typedefs.hpp"
|
||||
|
||||
#include "play_controller.hpp"
|
||||
#include "resources.hpp"
|
||||
#include "team.hpp"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
namespace wb
|
||||
{
|
||||
|
||||
/**
|
||||
* visitor_base: A base class template, using the so-called CRTP
|
||||
* If you want visit_all() and reverse_visit_all() in your class,
|
||||
* you should derive from this class.
|
||||
* Derived classes can "override" the following:
|
||||
* visit, pre_visit_team, post_visit_team
|
||||
* Derived classes should declare visitor_base<Derived> as a friend, or
|
||||
* else make the overridden functions public.
|
||||
* I recommend making the inheritance private or protected.
|
||||
*/
|
||||
template<typename Derived>
|
||||
class visitor_base
|
||||
{
|
||||
public:
|
||||
void visit_all() {visit_all_helper<false>();}
|
||||
void reverse_visit_all() {visit_all_helper<true>();}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* visit():
|
||||
* @return Whether or not to continue any visitation after this action.
|
||||
* The fcn is commented out because derived classes are required to implement it.
|
||||
*/
|
||||
//bool visit(size_t team_index, team&, side_actions&, side_actions::iterator);
|
||||
|
||||
///@return Whether or not to visit any of the contents of sa.
|
||||
bool pre_visit_team(size_t team_index, team& t, side_actions& sa) {return true;}
|
||||
///@return Whether or not to visit any more teams after this one.
|
||||
bool post_visit_team(size_t team_index, team& t, side_actions& sa) {return true;}
|
||||
|
||||
private:
|
||||
template<bool reverse>
|
||||
void visit_all_helper()
|
||||
{
|
||||
Derived* const new_this = static_cast<Derived*>(this);
|
||||
|
||||
size_t const current_team = resources::controller->current_side() - 1;
|
||||
size_t const num_teams = resources::teams->size();
|
||||
for(size_t iteration = 0; iteration < num_teams; ++iteration)
|
||||
{
|
||||
size_t const team_index
|
||||
= (current_team+num_teams+(reverse? -1-iteration: iteration)) % num_teams;
|
||||
team& t = resources::teams->at(team_index);
|
||||
side_actions& sa = *t.get_side_actions();
|
||||
if(!new_this->pre_visit_team(team_index,t,sa))
|
||||
continue; //< Skip this team's actions
|
||||
|
||||
if(reverse)
|
||||
{
|
||||
side_actions::reverse_iterator itor = sa.rbegin();
|
||||
side_actions::reverse_iterator end = sa.rend();
|
||||
while(itor!=end) {
|
||||
++itor;
|
||||
if(!new_this->visit(team_index,t,sa,itor.base()))
|
||||
return; //< Early abort
|
||||
}
|
||||
}
|
||||
else //forward
|
||||
{
|
||||
side_actions::iterator itor = sa.begin();
|
||||
side_actions::iterator end = sa.end();
|
||||
for(; itor!=end; ++itor)
|
||||
if(!new_this->visit(team_index,t,sa,itor))
|
||||
return; //< Early abort
|
||||
}
|
||||
if(!new_this->post_visit_team(team_index,t,sa))
|
||||
break; //< Early abort
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstract base class for all the visitors (cf GoF Visitor Design Pattern)
|
||||
* the whiteboard uses.
|
||||
|
|
Loading…
Add table
Reference in a new issue