3

假设我有一堂课X

class X {
    // ...
    size_t hash() const { return ...; }
};

我想创建一个std::tr1::unordered_map<X, int, HashFn>我想 X::hash()作为HashFn. 我知道我可以声明我自己的仿函数对象。我觉得应该有一种方法可以通过直接将指针传递给X::hash().

有没有?

4

4 回答 4

2

不,没有。原因是用作 HashFn 的任何内容都必须采用单个参数,该参数是对容器中对象的 const 引用。 X::hash接受单个参数,它是指向容器中对象的 const指针this(在这种情况下,指针是隐式的第一个参数),因此无法自行使用该函数。

你可能使用了一些绑定魔法,使用 boost::lambda 和 boost::bind。我不完全确定如何,但它可能看起来像这样:

boost::bind(&X::hash, &_1);

它创建了一个函数对象,它将使用指针调用 X::hash。

于 2011-04-11T14:43:15.937 回答
2

不; 正如您所展示的,您需要一个小型实用程序结构:

#include <functional>

template<typename T, std::size_t (T::*HashFunc)() const = &T::hash>
struct hasher : std::unary_function<T, std::size_t>
{
    std::size_t operator ()(T const& t) const
    {
        return (t.*HashFunc)();
    }
};

然后你可以创建一个unordered_map这样的:

std::tr1::unordered_map<X, int, hasher<X> > m;
于 2011-04-11T14:50:14.347 回答
0
size_t hash() const { return ...;}

计算哈希值的函数采用Key您的函数不采用的类型参数。因此,它的签名一开始就是错误的。

既然你想实现一个函数,而不是一个仿函数,那么应该这样做:

size_t hash(const KeyType &key) 
{
    return /*calculate hash and return it*/;
}

使其成为static成员函数并将其作为成员函数传递X::hash或使其成为自由函数,是您的选择。

于 2011-04-11T14:43:21.650 回答
0

你不能直接,但你可以包装它。最简单的方法是使用boost::mem_fn(),或者如果您的编译器支持它们,则使用标准等效项:(tr1::mem_fn()来自 TR1)或std::mem_fn()(来自 C++11)。

编辑:其实它不是那么简单。mem_fn()对于函数参数可以正常工作,但由于未指定其返回类型,因此很难用作模板参数。如果您有 C++11 支持,您可以使用它decltype来查找类型;否则你可能最好写你自己的函数对象,就像你提到的那样。

于 2011-04-11T14:44:20.010 回答