Friday, November 4, 2011

Recursive Templates -- Iterable poly dimensional associative arrays

And here is the template based array with a iterator added to it that is capable of iterating all the final cells in the array. Its not the most efficient but it works. Also note the operator<< is a bit busted at the moment.. Will fix it when im not about to fall asleep.
//built with mimggw g++ (gcc version 4.5.0 (GCC))
#include <iostream>
#include <map>
#include <string>
#include <ostream>

//ploy dimensional iterators
// what we are dealing with here is a N dimensional deep map

template <int n, typename Key, typename Value > 
class MultiDimMap
{
public:
//problem here for types u cant reach inside of the yet to be defined struct and get its type. You need to have it pre-definable.  
  typedef MultiDimMap<n-1, Key, Value>  InnerMapClass;
  typedef std::map<Key, InnerMapClass>  MapClass;

  //instance depend types.
  //"typename" is need here so the compiler knows we are pointing 
  //to a type that is not yet a solid implementation.
  typedef typename InnerMapClass::iterator InnerMapClassItr;
  typedef typename MapClass::iterator      MapClassItr;

  class iterator 
  {
  public:
    Value&    operator*()  { return *inner; }
    iterator& operator++()
    {
      ++inner; 
      valid_or_next(); 
      return *this;
    }
    bool      operator!=(const iterator& oit) const
    { 
      return (oit.outer != outer          && 
              (map->end() == outer         ||
        oit.map->end() == oit.outer ||
        oit.inner != inner)); 
    }
    bool      operator==(const iterator& oit) const { return !(oit != *this);  }

    std::ostream& print(std::ostream& out) { out << outer->first << ":"; inner.print(out); return out; } 

    iterator() :
      map(NULL),
      outer(),
      inner()
    {}
    iterator(MapClass& map_, const MapClassItr& outer_) :
      map(&map_),
      outer(outer_),
      inner()
    {
      inner = outer->second.begin();
      valid_or_next();
    }
        
  private:
    void valid_or_next()
    {
      while(
           (map->end() != outer) &&
           (outer->second.end() == inner) 
           )
       {
         ++outer;
         inner = outer->second.begin();
      }
    }

    MapClass* map;  
    MapClassItr outer;
    InnerMapClassItr inner;
  };
  
  iterator begin() { return iterator(map, map.begin()); }
  iterator end()   { return iterator(map, map.end()  ); }
  
  InnerMapClass& operator[](Key key) { return map[key]; }

private:
  MapClass map;  
}; 

//The recursive termination.. 
template <typename Key, typename Value > 
class MultiDimMap<1, Key, Value > 
{
public:
  typedef std::map<Key, Value> MapClass;

  //instance depend types.
  //"typename" is need here so the compiler knows we are pointing 
  //to a type that is not yet a solid implementation.
  typedef typename MapClass::iterator MapClassItr;

  class iterator 
  {
  public:
    Value&    operator*()     { return it->second; }
    iterator& operator++() { it++; return *this; }
    bool      operator!=(const iterator& oit) const { return oit.it != it;  }
    bool      operator==(const iterator& oit) const { return !(oit != *this);  }

    std::ostream& print(std::ostream& out) const { out << it->first << ":" << it->second; return out; }

    iterator() : it() {}
    iterator(const MapClassItr& it_) : it(it_)  {}
  private:
    MapClassItr it;
  };
  
  iterator begin() { return iterator(map.begin()); }
  iterator end()   { return iterator(map.end()  ); }

  Value& operator[](Key key) { return map[key]; }
private:
  MapClass map;  
}; 

//this hates me fix it later
//template <int n, typename Key, typename Value > 
//std::ostream& operator<<( std::ostream& out, const typename MultiDimMap<n, Key, Value>::iterator& it )
//{
//  return it.print(out);
//}

int main()
{
  MultiDimMap<1, std::string, int> stringInt1DMap;
  stringInt1DMap["a"] = 2; 
  stringInt1DMap["b"] = 5;
  
  MultiDimMap<2, std::string, int> stringInt2DMap;
  stringInt2DMap["d"]["b"] = 5;
  stringInt2DMap["a"]["c"] = 2;
  stringInt2DMap["d"]["c"] = 3;

  MultiDimMap<3, int, std::string> intString3DMap;
  intString3DMap[2][1][1] = "first";
  intString3DMap[1][1][2] = "second";
  intString3DMap[2][2][1] = "third";

  std::cout << "1d Iteration:" << std::endl;
  MultiDimMap<1, std::string, int>::iterator it1d;
  for(it1d  = stringInt1DMap.begin();
      it1d != stringInt1DMap.end();
      ++it1d)
    {
      std::cout << " ";
      it1d.print(std::cout); 
      std::cout << " Value:" << *it1d << std::endl;
    }

  std::cout << "2d Iteration:" << std::endl;
  MultiDimMap<2, std::string, int>::iterator it2d;
  for(it2d  = stringInt2DMap.begin();
      it2d != stringInt2DMap.end();
      ++it2d)
    {
      std::cout << " ";
      it2d.print(std::cout); 
      std::cout << " Value:" << *it2d << std::endl;
    }

  std::cout << "3d Iteration:" << std::endl;
  MultiDimMap<3, int, std::string>::iterator it3d;
  for(it3d  = intString3DMap.begin();
      it3d != intString3DMap.end();
      ++it3d)
    {
      std::cout << " ";
      it3d.print(std::cout); 
      std::cout << " Value:" << *it3d << std::endl;
    }
}

No comments:

Post a Comment