在将用作 unordered_map 对象的模板参数的内部结构定义中使用 class 成员变量保存函数

Using class member variables that hold functions in definition of inner structures that will be used as template arguments of an unordered_map object

我正在实现一个使用 unordered_map 的对象。对象是要通用的,所以模板无处不在。特别是 operator==operator() 被包装到 unordered_map 使用的结构中,分别检查键是否相等并为键生成哈希值。我希望用户编写自己的函数来实现上述两个运算符并将这些方法作为输入传递给 class 对象。然后结构将使用这些对象。我在使用示波器时遇到了一些麻烦,似乎不知道该怎么做。这是我的代码:

#include <unordered_map>
#include <iostream>
#include <string>
#include <functional>

template <typename O>
class aClass
{
public:
    aClass( bool        (usrIsEq)(O, O) , 
            std::size_t (usrHashFtn)(O) ) 
    {
        this->usrIsEq    = usrIsEq;
        this->usrHashFtn = usrHashFtn;
    }

    void add(O k, std::string v)
    {
        iTable[ {k} ] = v;
    }

    std::string get(O k)
    {
        return iTable[ {k} ];
    }


private:
    bool        (*usrIsEq)(O, O);
    std::size_t (*usrHashFtn)(O);

    struct Key
    {
        O obj;

        bool operator==(const Key &other)    const
        {
            std::cout <<  "obj " <<   obj << std::endl;
            return usrIsEq(obj, other.obj);
        }
    };

    struct KeyHasher
    {
        std::size_t operator()(const Key &k) const
        {
            return usrHashFtn(k);
        }
    };  
    std::unordered_map<Key, std::string, KeyHasher> iTable;

};

bool isEqInts(int a, int b)
{
    return a == b;
}

std::size_t intHashFtn(int x)
{
    std::hash<int> hf;
    return  hf(x);
}

int main()
{
    aClass<int> x(isEqInts, intHashFtn);
    x.add( 1, std::string("hello") );
}

我不完全确定如何实现 structs KeyKeyHasher 以便它们使用 class 中包含的函数。我真正关心的唯一一件事是函数作为 class 构造函数的输入。其他的都可以报废。

困扰您的主要问题是 Key 不知道 usrIsEqKeyHasher 不知道 usrHashFtn。您需要将指向 aClass 对象的指针或引用传递给那些 类.

这里有一个建议:

struct Key
{
    O obj;
    aClass* ac;

    bool operator==(const Key &other)    const
    {
        std::cout <<  "obj " <<   obj << std::endl;
        return ac->usrIsEq(obj, other.obj);
    }
};

struct KeyHasher
{
    std::size_t operator()(const Key &k) const
    {
        return k.ac->usrHashFtn(k.obj);
    }
};  

并更新您使用 Key 访问 table 的地方:

void add(O k, std::string v)
{
    iTable[{k, this}] = v;
}

std::string get(O k)
{
    return iTable[{k, this}];
}