Figure 1: The template function rVisit

template <class CompositeType, class ProcessType>
int rVisit(CompositeType &cobj, ProcessType &pobj)
{
   // "stack" of composite handles
   deque<ProcessType::CompositeHandle> cdeq;

   // number of composites at current level
   deque<int> ndeq; 

   // temporary vectors of simple and composite handles
   vector<ProcessType::SimpleHandle> svec;
   vector<ProcessType::CompositeHandle> tempcvec;

   int depth = 0;
   bool searching = true;
   bool done = false;
   int count = 0;

   while(!done)
   {
      if(searching)
      {
         // clear simple and composite handle vectors
         svec.erase(svec.begin(), svec.end());
         tempcvec.erase(tempcvec.begin(), tempcvec.end());

         // get hanles at this level
         pobj.getHandles(cobj, tempcvec, svec);
         ndeq.push_back(tempcvec.size());

         // push CompositeHandles to stack in reverse order
         for(int i = tempcvec.size()-1; i >= 0; --i)
            cdeq.push_back(tempcvec[i]);

         // process elements at this level
         for(int i = 0; i < tempcvec.size(); ++i)
         {
            pobj.processComposite(cobj, tempcvec[i]);
            count++;
         }
         for(int j = 0; j < svec.size(); ++j)
         {
            pobj.processSimple(cobj, svec[j]);
            count++;
         }
         searching = false;
      }
      else // in not-searching state
      {
         if(ndeq.back() > 0) // more unexpanded composites
         {                   // try to move down a level
            pobj.moveDownTo(cobj, cdeq.back());
            assert(cdeq.size() > 0);
            cdeq.pop_back();
            ndeq.back()--;
            depth++;
            searching = true;
         }
         else // no more unexpanded composites
         {    // try to move back up a level
            if(depth > 0) // we can move up
            {
               assert(ndeq.size() > 0);
               ndeq.pop_back();
               pobj.moveUp(cobj);
               depth--;
            }
            else         // already at top -- we're done
            {
               assert(ndeq.size() > 0);
               ndeq.pop_back();
               done = true;
            }
         }
      }
   }
   assert(ndeq.size() == 0);
   assert(cdeq.size() == 0);
   assert(depth == 0);
   return count;
}