gpt4 book ai didi

c++ - 为依赖类型特化 std::hash

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:53:12 25 4
gpt4 key购买 nike

我已经定义了这个模板类结构:

template<typename T> struct Outer {
struct Inner { /* ...some stuff... */ };
};

我想把Inner对象变成 unordered_map (实际上,不是直接指定它们,而是它们的容器,因此直接在 unordered_map 的模板参数上指定散列对象的方法不是一个好主意),因此我想专门化 hash这些项目的类。

这行不通,因为编译器无法匹配Outer<T>::Inner使用实例化时指定的类型 hash :

namespace std {
template<typename T> struct hash<typename Outer<T>::Inner > {
size_t operator ()( typename Outer<T>::Inner const & obj )
{ /* ...some stuff... */ }
};
};

有人知道解决这个问题的方法吗?

最佳答案

你显然是对的,这行不通,因为编译器无法匹配基于此类依赖类型的模板特化(例如,Inner 可能是嵌套的 typedef,那么编译器将如何分辨差异在来自 Outer 中的嵌套 typedef 的类型与来自其他地方的类型之间?它不能,这是不可能分辨的)。

有很多解决方案。

首先,您可以将内部类移到外部类的外部(如果需要,让它们成为 friend )。您还可以将其移至“详细信息”命名空间或根据您的上下文以多种其他方式隐藏它。人们避免此类嵌套的“内部”类的情况并不少见,因为它们可能会导致许多此类问题,并且一些较旧的编译器甚至根本无法接受此类嵌套类。将那些嵌套类移出外部类通常是更好的做法。就实际代码而言,您可以这样做:

template <typename T>
struct Outer; // forward-decl.

namespace detail {
template <typename T>
struct Outer_Inner {
friend class Outer<T>; // Optional

// ....

};
};

template <typename T>
struct Outer {
typedef detail::Outer_Inner<T> Inner;
friend class detail::Outer_Inner<T>; // Optional

// ...

};

namespace std {
template<typename T>
struct hash< detail::Outer_Inner<T> > {
// ..
};
};

另一种解决方案是定义您自己的哈希类,您可以将其提供给 unordered_set .像这样:

template <typename T>
struct Outer {

struct Inner {
//..
};

struct InnerHash {
typedef Inner argument_type;
typedef std::size_t result_type;

result_type operator()(argument_type const& s) const {
return /* some hashing code */;
};
};

// ...

// An example unordered-set member:
std::unordered_set<Inner, InnerHash> m_set;

};

最后,还有一个我能想到的解决方案,就像第一个解决方案一样,具有专门化 std::hash 的优势。类模板。然而,这个解决方案有点复杂,它涉及将您的内部类包装到外部类模板中,如下所示:

template <typename T>
struct InnerWrapper {
typedef typename Outer<T>::Inner value_type;
value_type data;
};

然后创建特化 std::hash< InnerWrapper<T> > .该解决方案实际上仅具有不干扰外部类的现有实现的优势,但会创建一个unordered_map。在这种情况下意味着 map 必须包含(直接或间接) InnerWrapper 对象而不是直接存储 Inner 对象。此外,您应该注意到,通过在嵌套类中实现与 Outer 更紧密集成的 Inner 的一些功能,并在外部实现更“公共(public)”的 Inner 功能,您应该注意到该解决方案可以与第一个解决方案混合使用类,从而避免友元关系并允许更紧密的外部-内部集成,同时留下一个干净的面向用户的类来访问内部的功能。

关于c++ - 为依赖类型特化 std::hash<T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25242556/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com