Search code examples
c++objecthashoperator-overloadinguser-defined-types

C++ - type qualifiers error when hashing user defined object


I currently have a user defined class called ResultTableEntry and I would like to be able to create an std::unordered_set. I found out that would have a create a hash function for my class in order for me to initialise the set.

#include <vector>
#include <string>

class ResultTableEntry {
private:
    int relIndex;
    std::vector<int> paramIndex;
    std::vector<std::string> result;

public:
    ResultTableEntry::ResultTableEntry(int, std::vector<int>, std::vector<std::string>);

    int getRelationshipIndex();
    std::vector<int> getParameterIndex();
    std::vector<std::string> getResult();
};

namespace std {

    template <>
    struct hash<ResultTableEntry>
    {
        std::size_t operator()(const ResultTableEntry& k) const
        {

            size_t res = 17;
            for (auto p : k.getParameterIndex()) {
                res = res * 31 + hash<int>()(p);
            }
            for (auto r : k.getResult()) {
                res = res * 31 + hash<std::string>()(r);
            }
            res = res * 31 + hash<int>()(k.getRelationshipIndex());
            return res;
        }
    };
}

I implemented my hash function according to: C++ unordered_map using a custom class type as the key

However, I kept facing these errors.

  • the object has type qualifiers that are not compatible with the member function "ResultTableEntry::getParameterIndex"
  • the object has type qualifiers that are not compatible with the member function "ResultTableEntry::getResult"
  • the object has type qualifiers that are not compatible with the member function "ResultTableEntry::getRelationshipIndex"
  • expression having type 'const std::hash' would lose some const-volatile qualifiers in order to call 'size_t std::hash::operator ()(ResultTableEntry &)'

Removing 'const' in the parameter doesn't seem to help too. Is there something wrong with my implementation? I won't be able to use other library like boost.


Solution

  • You need to assure the compiler that the member functions will not modify the *this pointer

    #include <vector>
    #include <string>
    
    class ResultTableEntry {
    private:
        int relIndex;
        std::vector<int> paramIndex;
        std::vector<std::string> result;
    
    public:
        ResultTableEntry(int, std::vector<int>, std::vector<std::string>);
    
        int getRelationshipIndex() const;
        std::vector<int> getParameterIndex() const;
        std::vector<std::string> getResult() const;
    };
    
    namespace std {
    
        template <>
        struct hash<ResultTableEntry>
        {
            std::size_t operator()(const ResultTableEntry& k) const
            {
                size_t res = 17;
                for (auto p : k.getParameterIndex()) {
                    res = res * 31 + hash<int>()(p);
                }
                for (auto r : k.getResult()) {
                    res = res * 31 + hash<std::string>()(r);
                }
                res = res * 31 + hash<int>()(k.getRelationshipIndex());
                return res;
            }
        };
    }