1

I want to build a hash table using a linked list

But there is a problem during compilation

I have tried using an array instead of a vector, but still the same result

Maybe it has something to do with the template?

I don't understand the sample code related to template

Here is some code that reproduces the problem, along with the error message

#include <iostream>
#include <vector>

using namespace std;

struct node
{
    string key;
    string value;
    node* next;
};

class HashTable
{
private:
    vector<node*> bucket;
    long long int capacity;
public:
    HashTable(long long int max_size = 100)
    {
        capacity = max_size;
        bucket.reserve(capacity);
        bucket.resize(capacity);
        fill(bucket.begin(), bucket.end(), NULL);
    }
};
Build started...
1>------ Build started: Project: C++ Test, Configuration: Debug x64 ------
1>C++ Test.cpp
1>E:\Other\Visual Studio\VC\Tools\MSVC\14.33.31629\include\xutility(4519,24): error C2440: '=': cannot convert from 'const _Ty' to 'node *'
1>        with
1>        [
1>            _Ty=int
1>        ]
1>E:\Other\Visual Studio\VC\Tools\MSVC\14.33.31629\include\xutility(4519,24): message : Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or parenthesized function-style cast
1>C:\Users\DaLaw2\source\repos\C++ Test\C++ Test.cpp(30): message : see reference to function template instantiation 'void std::fill<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<_Ty>>>,int>(const _FwdIt,const _FwdIt,const int &)' being compiled
1>        with
1>        [
1>            _Ty=node *,
1>            _FwdIt=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<node *>>>
1>        ]
1>Done building project "C++ Test.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
DaLaw2
  • 21
  • 3
  • 2
    `#include ` -- I bet you didn't get this from a good C++ book, but from an online website that has a poor reputation for teaching C++. Get rid of that header and use the proper ones, i.e. ``, ``, etc. You then get into the habit of learning what the appropriate headers are when you write a C++ application. – PaulMcKenzie Oct 19 '22 at 13:03
  • ...and the backslash in `#include ` implies that you're using it on Windows. – Ted Lyngmo Oct 19 '22 at 13:03
  • 1
    [Why should I not #include ?](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h) - *Never* ever include that header. – Jesper Juhl Oct 19 '22 at 13:05
  • You forgot `` and ``. Also `using namespace std;` should not be there. – PaulMcKenzie Oct 19 '22 at 13:07
  • I've learned the downsides of using stdc++.h already edited – DaLaw2 Oct 19 '22 at 13:09
  • `fill(bucket.begin(), bucket.end(), NULL);` -- Use `nullptr`, not NULL. To be honest, all of your errors/issues with the code stem from not getting the proper reading material when learning C++, and following best (or even better) practices when writing a C++ program. – PaulMcKenzie Oct 19 '22 at 13:09
  • @DaLaw2 the `` thing and `using namespace std;` are _very common_ mistakes that are seen on here on perhaps 50%+ of the questions asked. They both have _significant_ downsides, so you'll see a lot of comments about them. Feel free to look further into why `using namespace std;` is bad, particularly in a header file. – Rogue Oct 19 '22 at 13:11
  • @DaLaw2 Please don't vandalize your own question. The way you changed it made the existing answers not making sense - and also, the edited code can not be used to produce the error message you have in the question. I rolled back that edit. – Ted Lyngmo Oct 19 '22 at 13:19
  • This is my first time asking a question. sorry – DaLaw2 Oct 19 '22 at 13:22
  • @DaLaw2 No problem. Just think about the fact that the question and the answers may be read by many people in the future, so the question and the answers should preferably talk about the same thing. So, avoid changing the question so that any existing answers suddenly doesn't make sense. Also, didn't you notice that the changes you made to the code in the question made the code compile fine? – Ted Lyngmo Oct 19 '22 at 13:26
  • You might also change your bucket to std::vector to avoid memory leaks. Another common mistake is to use pointers/new/delete too much. – Pepijn Kramer Oct 19 '22 at 13:26
  • @Pepijn Kramer I'll give it a try – DaLaw2 Oct 19 '22 at 13:32

2 Answers2

6

First, include the proper headers:

#include <algorithm>  // fill
#include <cstddef>    // size_t
#include <string>     // string
#include <vector>     // vector

Then don't use NULL that may be defined as a simple 0 which does not match the node* you want for std::fill. Use nullptr. You also do not need to reserve just before you resize.

class HashTable {
private:
    std::vector<node*> bucket;
    // std::size_t capacity;       // use bucket.capacity() instead

public:
    HashTable(std::size_t max_size = 100) {
        bucket.resize(max_size);
        std::fill(bucket.begin(), bucket.end(), nullptr);
    }

    std::size_t capacity() const { return bucket.capacity(); }
};

The fill operation is not necessary though since the resize operation will zero initialize all the pointers anyway.

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • I don't quite understand what the last line means About std::size_t ... – DaLaw2 Oct 19 '22 at 13:30
  • @DaLaw2 It means that the member function `capacity` returns a value of type `std::size_t` (which is a type alias for some `unsigned` integer type). – Ted Lyngmo Oct 19 '22 at 13:31
  • `bucket` is empty in the ctor, so it could be just `bucket.resize(max_size, nullptr);` (technically, the second argument is redundant). If `bucket` were not empty, it could've been `bucket.assign(max_size, nullptr);`. – Evg Oct 19 '22 at 13:52
  • 1
    @Evg Yes or even better, as Caleth showed using the member initializer list - but I wanted to stay close to OPs code since it's in the `fill` with `NULL` the problem occurs and replacing `fill(..., NULL)` with `fill(..., nullptr)` solves the problem. – Ted Lyngmo Oct 19 '22 at 13:53
3

Whilst NULL is a null pointer literal, it isn't required to be an expression of pointer type.

You could use nullptr, however the resize has done that for you, and the constructor of std::vector could have done that too.

#include <cstddef>
#include <string>
#include <vector>

struct node
{
    std::string key;
    std::string value;
    node* next;
};

class HashTable
{
private:
    std::vector<node*> bucket;
    // we don't need to repeat bucket.capacity() as a data member
public:
    HashTable(std::size_t max_size = 100)
      : bucket(max_size)
    {
        // we don't need to reserve, we've constructed a vector of appropriate size
    }
};
Caleth
  • 52,200
  • 2
  • 44
  • 75