Iteratoren mit Zeigern in dynamische Datenstrukturen

Content

Wenn wir mit Iteratoren und dynamischen Datenstrukturen operieren, müssen wir festlegen, was mit Iteratoren geschieht, wenn die referenzierte Datenstruktur abgebaut wird. Theoretisch wäre es denkbar, die Datenstruktur dann weiterzubestehen lassen. Dies würde aber eine weitere Indirektion kosten, da dann die gesamte Datenstruktur hinter einen weiteren std::shared_ptr versteckt werden müsste, auf den der Iterator zeigt. Normalerweise wird aber (wie in der STL) davon ausgegangen, dass den Iteratoren die dynamischen Datenstrukturen nicht gehören.

Fragen und Aufgabe

Aufgabe

Vorlage

#ifndef HASH_HPP
#define HASH_HPP

#include <cstdlib>
#include <functional>
#include <memory>
#include <utility>

template<typename Key, typename Value>
class Hash {
   public:
      using Object = std::pair<const Key, Value>;
      Hash(std::size_t dim) :
	 dim(dim), bucket(std::make_unique<NodePtr[]>(dim)) {
      }
      bool insert(Object object) {
	 auto index = hash(object.first) % dim;
	 auto ptr = bucket[index];
	 while (ptr && ptr->object.first != object.first) {
	    ptr = ptr->next;
	 }
	 if (ptr) return false;
	 bucket[index] = std::make_shared<Node>(std::move(object),
	    bucket[index]);
	 return true;
      }
      template<typename F>
      void for_each(F&& f) {
	 for (std::size_t index = 0; index < dim; ++index) {
	    auto ptr = bucket[index];
	    while (ptr) {
	       f(ptr->object);
	       ptr = ptr->next;
	    }
	 }
      }
   private:
      struct Node;
      using NodePtr = std::shared_ptr<Node>;
      struct Node {
	 Node(Object object) : object(std::move(object)) {
	 }
	 Node(Object object, NodePtr next) :
	    object(std::move(object)), next(next) {
	 }
	 Object object;
	 NodePtr next;
      };
      const std::size_t dim;
      std::unique_ptr<NodePtr[]> bucket;
      std::hash<Key> hash;
};

#endif
#include <iostream>
#include <string>
#include "Hash.hpp"

int main() {
   Hash<std::string, unsigned int> hash(32);
   std::string town; unsigned int population;
   while (std::cin >> town && std::cin >> population) {
      if (!hash.insert(std::make_pair(town, population))) {
	 std::cerr << "insertion of " << town << " failed." << std::endl;
      }
   }
   hash.for_each([](auto& object) {
      std::cout << object.first << " " << object.second << std::endl;
   });
}