专门为模板类中的嵌套类使用std :: hash

Amb*_*jak 5 c++ hash templates nested stdhash

我有一个Baz包含嵌套类的模板类Sub.我想通过专门化std :: hash为这个子类定义一个哈希函数.但是,它似乎不起作用.

#include <functional>

struct Foo {
    struct Sub {
    };
};

template <class T>
struct Bar {
};

template <class T>
struct Baz {
    struct Sub {
        int x;
    };
};

// declare hash for Foo::Sub - all right
namespace std {
    template <>
    struct hash< Foo::Sub >;
}

// declare hash for Bar<T> - all right
namespace std {
    template <class T>
    struct hash< Bar<T> >;
}

// declare hash function for Baz<T>::Sub - doesn't work!
namespace std {
    template <class T>
    struct hash< Baz<T>::Sub >;
}

// Adding typename produces a different error.
namespace std {
    template <class T>
    struct hash< typename Baz<T>::Sub >;
}
Run Code Online (Sandbox Code Playgroud)

Gcc 4.5.3抱怨:

$ g++ -std=c++0x -c hash.cpp
hash.cpp:34:30: error: type/value mismatch at argument 1 in template parameter list for ‘template<class _Tp> struct std::hash’
hash.cpp:34:30: error:   expected a type, got ‘Baz<T>::Sub’
hash.cpp:40:12: error: template parameters not used in partial specialization:
hash.cpp:40:12: error:         ‘T’
Run Code Online (Sandbox Code Playgroud)

UPDATE

我真正想要做的是实现一个容器,它支持其中的元素的稳定引用(不是在C++意义上).我想允许用户将这些引用插入std::unordered_set和类似,并使用它们有效地访问或修改现有元素.以下只是一个模型,而不是我正在实现的确切容器.问题在于为引用类型定义哈希函数.

template <class T>
class Container {
public:
    class Reference {
    public:
        // operator==, operator!=, operator< ...., isNull()
    private:
        size_t index; // index into m_entries (or could be anything else)
        // possibly more stuff
    };

    Reference insert (const T &value);
    Reference find (const T &value);
    void remove (Reference r);
    Reference first ();
    Reference next (Reference prev);

private:
    struct Entry { T value, ... };

    std::vector<Entry> m_entries;
};
Run Code Online (Sandbox Code Playgroud)

Edw*_*nge 2

这个问题的答案是,你想做的事情根本不可能做到。编译器无法确定哪个外部类包含子类型。考虑一下为什么:

struct outer1 { typedef int Sub; };
struct outer2 { typedef int Sub; };
Run Code Online (Sandbox Code Playgroud)

当编译器获得 Sub 时,它如何确定你想要哪个外部?这不可以。这是不可能的。

在你的情况下,虽然非常困难,但还是有可能根据 T 派生 IFF Sub 。但这需要编译器知道 Sub 来自哪里,但事实并非如此。

所以你根本不能这样做。没办法,没办法。

如果您需要一些通用方法来查找适合您类型的哈希函数,那么您需要创建一个元函数 get_hash。默认情况下,它可以查找“hash_type”内部 typedef,并针对标准哈希值进行覆盖。打字很多...

或者,将 Sub 放在包含类之外作为其自己的模板,并在那里使用 typedef 而不是内部类。然后您可以在模板上专门化哈希。

否则,只需将您知道需要的哈希值提供给您正在使用的模板的哈希函数参数即可。