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

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 保存 定义 函数 在内部 变量      更新时间:2023-10-16

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

#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") );
}

我不完全确定如何实现structKeyKeyHasher,以便它们使用类中包含的函数。我真正关心的唯一一件事是,这些函数是作为输入提供给类构造函数的。

让你困惑的主要问题是Key不知道usrIsEq, KeyHasher不知道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访问表的位置:

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