0

I am learning templates and am struggling to set up my put method without compiler errors. Can someone point me in the right direction? The commented sections are not implemented yet, but based on an Integer-key, String-value implementation.

The concrete error I am having: Severity Code Description Project File Line Suppression State Error C2923 'HashTable<int,std::string>::HashItem': 'key' is not a valid template type argument for parameter 'Key'

#pragma once

#include <cmath>
#include <iostream>
#include <list>

using namespace std;

template<typename Key, typename Value>
class HashTable
{
  template<typename Key, typename Value>
  class HashItem {
  public: 
    Key key;
    Value value = nullptr;
    bool operator==(const HashItem& hi) const { return key == hi.key && value == hi.value; }
    HashItem(const Key& k, const Value& v) 
      : key(k), value(v) {}
    // for part b)
    HashItem& operator=(const Value& v) { 
      this->value = v; 
      return *this; 
    }
    operator string() { return this->value; }
  };

  list<HashItem<Key, Value>>* table;
  int current_total = 0;

  float FILL_LEVEL = 0.8; // Füllgrad, between 0 and 1

  // not const:
  int CAPACITY = 100; // default value

  // for hash functions/preparing for use with strings:
  const int PRIME_CONST = 31;

  int hash_function(string key);
  int hash_function(int key);
  // std::hash?

  void rehash();

public:
  HashTable() {
    cout << "ht cstructed, intitial_capacity is (default:) " << CAPACITY << endl;
  }
  HashTable(int initial_capacity) {
    cout << "ht cstructed, intitial_capacity is " << initial_capacity << endl;
    CAPACITY = initial_capacity;
  }

  //// RULE OF THREE
  //// copy ctor
  //HashTable(HashTable& const ht);
  //// destructor
  //~HashTable();
  //// (copy) assignment operator
  //HashTable& operator=(HashTable& const ht);

  //// RULE OF FIVE
  //// move ctor
  //HashTable(HashTable&& ht); // && -> rvalue
  //// move assignment operator
  //HashTable& operator=(HashTable&& ht);

  //// Hash Table operations
  void put(Key key, Value value) {
    // allocate memory with first put
    if (current_total == 0)
      table = new list<HashItem<key, value>>[CAPACITY];

    HashItem<key, value>* hi = new HashItem(key, value);
    int hash = hash_function(key);

    if (find(table[hash].begin(), table[hash].end(), *hi) == table[hash].end()) {
      // only put if not already in list
      table[hash].push_back(*hi);
    }

    current_total++;
    //cout << "current total is " << current_total << " of " << FILL_LEVEL * CAPACITY << endl;

    // rehash check
    if (current_total > (FILL_LEVEL * CAPACITY)) {
      rehash();
      //cout << "fill level reached: rehashed" << endl;
    }
  }
  //void remove(int key, string value);
  //string get(int key);

  //// for part b)
  //HashItem& get_item(int key) {
  //  int list_index = hash_function(key); // list_index = hash_code
  //  if (!table[list_index].empty()) {
  //    for (auto &list_item : table[list_index]) {
  //      if (key == list_item.key) {
  //        return list_item;
  //      }
  //    }
  //  }
  //  HashItem hi(key, "");
  //  return hi;
  //}

  //friend ostream& operator<<(ostream& os, const HashTable& ht);
  //void clear();
  //bool contains(int key);
  //bool contains_value(string value);

  //// fill levels
  //void set_fill_level(float new_level);
  //float get_fill_level();

  //// b) 
  //// Overloading [] operator to access elements in array style
  //HashItem& operator[] (int key) { 
  //  if (this != nullptr)
  //    return this->get_item(key); 
  //  HashItem hi(key, "");
  //  // stand-in hash item in case not in hash table
  //  return hi;
  //}
};


Call in my main.cpp:

#include <iostream>

#include "HashTable.h"

using namespace std;

#define DEBUG(X) cout << (#X) << " = " << (X) << endl

HashTable<int, string> ht;

void put_test() {
  cout << "--------------- put test ----------------------------------" << endl;
  ht.put(10, "test");
}

int main() {
  
  put_test();
}
marie_antoinette
  • 181
  • 2
  • 10
  • 1
    Not related, but very important point: Never use `using namespace std;` in header file! – sklott Dec 28 '22 at 20:40
  • `HashItem* hi` should be `HashItem* hi`. You need *types*, not objects for *typenames*. – Yksisarvinen Dec 28 '22 at 20:48
  • 2
    Better yet remove line `template` before line `class HashItem {` and use just `HashItem` instead of `HashItem`. – sklott Dec 28 '22 at 20:50
  • Also, you have memory leak. Why you doing `new HashItem(key, value);` if you never use this **pointer**? – sklott Dec 28 '22 at 20:52
  • [Why is "using namespace std;" considered bad practice?](https://stackoverflow.com/q/1452721/430766) – bitmask Dec 29 '22 at 00:56

0 Answers0