Project: finder, src: unordered_map.h


C++11 で追加された unordered_map を FreeBSD で実現するためのコード。但し、自信はない。
#ifndef STD_UNORDERED_MAP_H_
#define STD_UNORDERED_MAP_H_

#include <list>
#include <utility>
#include "EOFObjectException.h"

namespace std {

template<typename K, typename V, typename H>
class unordered_map {
  struct UOMPair : public pair<K, V> {
    bool operator == (const UOMPair &p) const {
      return (this->first == p.first);
    }
    UOMPair(const K &key, const V &value) : pair<K,V>(key, value) {}
    UOMPair() : pair<K, V>() {}
  };
#define HASH_SIZE (1024)
  H hash;
  std::list<UOMPair> *hashtable;

 public:
  unordered_map<K, V, H>() {
    hashtable = new std::list<UOMPair>[HASH_SIZE];
  };

  ~unordered_map<K, V, H>() {
    delete [] hashtable;
  }

  void clear() {
    for (int i = 0; i < HASH_SIZE; ++i) {
      hashtable[i].clear();
    }
  }

  V &operator[](const K &key) {
    std::list<UOMPair> &p = hashtable[hash(key) % HASH_SIZE];
    for (typename std::list<UOMPair>::iterator i = p.begin(); i != p.end(); ++i) {
      if (key == i->first) {
        return i->second;
      }
    }
    UOMPair tmp(key, V());
    p.push_back(tmp);
    return p.back().second;
  }

  // iterators
  class iterator {
    int pos;
    typename std::list<UOMPair>::iterator current;
    std::list<UOMPair> *hashtable;
    bool isEnd() {
      return pos == HASH_SIZE - 1 && current == hashtable[pos].end();
    }

   public:
    iterator() {}
    iterator(int pos, const typename std::list<UOMPair>::iterator &c, std::list<UOMPair> *h) : pos(pos), current(c), hashtable(h) {}
    bool operator == (const iterator &i) const {
      return pos == i.pos && current == i.current && hashtable == i.hashtable;
    }
    bool operator != (const iterator &i) const {
      return !(*this == i);
    }
    pair<K, V> operator *() {
      if (!isEnd()) {
        return pair<K, V>(*current);
      }
      throw EOFObjectException(__FILE__, __LINE__, "EOFObjectException");
    }
    iterator & operator ++() {
      if (!isEnd()) {
        if (current == hashtable[pos].end()) {
          current = hashtable[++pos].begin();
        } else {
          ++current;
        }
      }
      return *this;
    }
    iterator &operator ++(int dummy) {
      if (!isEnd()) {
        if (current == hashtable[pos].end()) {
          current = hashtable[++pos].begin();
        } else {
          ++current;
        }
      }
      return *this;
    }
  };
  typedef iterator const_iterator;

  // iterator operations
  iterator begin() {
    return iterator(0, hashtable[0].begin(), hashtable);
  }
  iterator end() {
    return iterator(HASH_SIZE - 1, hashtable[HASH_SIZE - 1].end(), hashtable);
  }
  iterator find(const K &key) {
    size_t h = hash(key) % HASH_SIZE;
    std::list<UOMPair> &p = hashtable[h];
    for (typename std::list<UOMPair>::iterator i = p.begin(); i != p.end(); ++i) {
      if (key == i->first) {
        return iterator(h, i, hashtable);
      }
    }
    return end();
  }
};

}

#endif //STD_UNORDERED_MAP_H_