如何声明哈希函数以在命名空间内的unordered_set中使用?

时间:2014-04-01 20:49:54

标签: c++ hash

我已成功为自定义类创建了哈希函数(和==覆盖),因此我可以在unordered_set中使用它。但是,理想情况下,我想在我要用于的类附近定义我的类的模板特化。这可以通过以下方式完成,工作正常:

class MyClass {
public:
    MyClass() { _id = _nextId++; }
    const int id() const { return _id; }
private:
    int _id;
    static int _nextId;
};

int MyClass::_nextId = 0;

template<>
struct std::hash<MyClass> {
    std::size_t operator()(const MyClass& k) const {
        return k.id();
    }
};

但是,MyClass在自定义命名空间中声明。我认为使用全局范围解析运算符::,但这不起作用:

namespace mine {
    // ...

    template<>
    struct ::std::hash<MyClass> {
        // ...
    };
}

因此,似乎我想在命名空间的封闭括号内有一些东西声明要在另一个命名空间中。写下最后一句话让我意识到这可能是不可能的,但是在类哈希函数附近使用哈希函数的想法似乎是一个好主意。

这可能吗?这是什么最好的做法?

2 个答案:

答案 0 :(得分:5)

正如您所发现的,如果您想为std::hash添加必须在std命名空间内完成的专门化。如果这是不合需要的,另一个选择是将哈希算子保留在命名空间中并将其作为模板参数传递给unordered_set

namespace mine {

class MyClass { ... };

struct MyClass_hash {
  std::size_t operator()(const MyClass& k) const {
    return k.id();
  }
};

}

std::unordered_set<mine::MyClass, mine::MyClass_hash> my_set;

您还可以为typedef创建unordered_set以节省一些打字费用。

答案 1 :(得分:1)

您可以将std::hash专门用于将其包含在标准命名空间中的类型:

namespace std {
    template <>
    struct hash<mine::MyClass> {
    std::size_t operator()( const mine::MyClass& k) const {
        return k.id();
    }
}

这是专门化std :: hash的方法。或者,您可以创建自定义仿函数并将其传递给哈希表。然后你可以做任何事情,例如:

namespace mine {

class MyClass { ... };

    template<typename T>
    struct Hash : public std::unary_function<T, uint16_t> {
        uint16_t operator()(T const&) const;
    };

typedef boost::unordered_multimap< MyClass, value, Hash<MyClass> > HashMMap;

}