简体   繁体   中英

Passing a member function as template argument

I have a hash table class. It has a template parameter hashFunction :

#include <string>

template<class KeyType> using hashFunction_t = size_t(size_t, const KeyType&);

template< class KeyType, class ValueType, int nHashGroups,
    hashFunction_t<KeyType> hashFunction >
class HashTable
{

};

class Entity
{
    //djb2
    size_t stringHash(size_t nGroups, const std::string& key)
    {
        unsigned long hash = 5381;
        const char* str = key.c_str();

        int c = 0;
        while (c = *str++)
            hash = ((hash << 5) + hash) + c;

        return hash % nGroups;
    }

    HashTable <std::string, int, 10, stringHash> ht; 
};

int main()
{
    Entity{};
}

I would prefer to hide stringHash function inside the Entity class as a private function but doing that gives me an error:

Error (active)  E0458   argument of type 
"size_t (Entity::*)(size_t nGroups, const std::string &key)" 
is incompatible with template parameter of type 
"hashFunction_t<std::string> *"

How can I do this?

The problem is that you are trying to use a pointer-to-member as a type template parameter, and this is not supported, basically because when you define a type you don't bind that type to any specific object.

When (as suggested in a comment) you make stringHash static, then you no longer need the object, so it can be used to define the type.

If you still need to have stringHash from a non-static member, then you can change the template to something like the below. Be aware that you have to pass the object to the HashTable in order to call the hashFunction . Also, keep an eye on the syntax to call it.

template<class KeyType, class Obj> using hashFunction_t =
    size_t(Obj::*)(size_t, const KeyType&);

template< class KeyType, class ValueType, int nHashGroups,
    class Obj, hashFunction_t<KeyType, Obj> hashFunction>
class HashTable
{
public:
    explicit HashTable(Obj& obj) : m_obj{obj} {
        (m_obj.*hashFunction)(10, ""); // arguments just for illustrative purposes
    }

private:
    Obj& m_obj; // keep a reference to the object to call the method
                // be careful with dangling references
};

class Entity
{
    size_t stringHash(size_t nGroups, const std::string& key)
    /* ... */

    // Pass a reference to the object
    HashTable <std::string, int, 10, Entity, &Entity::stringHash> ht{*this};
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM