C++ 如何扩展自定义类型的std::tr1::hash?

C++ 如何扩展自定义类型的std::tr1::hash?,c++,tr1,C++,Tr1,如何允许STL实现拾取自定义类型?在MSVC上,有一个类std::tr1::hash,我可以使用 namespace std { namespace tr1 { template <> struct hash<MyType> { ... }; } } 名称空间std { 名称空间tr1 { 模板 结构散列 { ... }; } } 但这是推荐的方式吗?此外,这是否也适用于GCC的实

如何允许STL实现拾取自定义类型?在MSVC上,有一个类
std::tr1::hash
,我可以使用

namespace std 
{
    namespace tr1 
    { 
        template <> 
        struct hash<MyType> 
        { ... };
    } 
}
名称空间std
{
名称空间tr1
{ 
模板
结构散列
{ ... };
} 
}

但这是推荐的方式吗?此外,这是否也适用于GCC的实施?对于
boost::hash
,只需提供一个免费函数
size\u t hash\u value(const MyType&)
,TR1实现是否有类似的功能?

是的,这也适用于GCC。我正在一个更大的项目中使用它,它可以毫无问题地工作。您也可以为TR1容器提供自己的自定义哈希类,但指定std::TR1::hash为默认哈希类。为自定义类型专门化它似乎是扩展标准散列功能的自然方式。

因为您没有添加到
std
库名称空间,而是只提供专门化,所以它完全可以


如果您想提供更通用的哈希方法(例如,通常对元组进行哈希),那么请查看Boost Fusion,这将适用于大多数情况(可能是元组中的元组除外)

我试图找出使用无序关联容器(也使用GCC,正如OP所问)执行此操作的确切语法,并回答了这个问题

不幸的是,它没有达到我想要的详细程度。通过查看gcc头文件,了解它们是如何实现标准哈希函数的,我让它工作起来了。 鉴于web上缺少示例(至少在撰写本文时),我认为这将是一个发布我自己的示例的好地方(我可以确认GCC的工作):


命名空间std{namespace tr1
{
模板
结构哈希:公共一元函数
{
size\u t运算符()(常量MyType&v)常量
{
return/*我的哈希算法*/;
}
};
}}

(注意这里有两个名称空间-这只是我折叠嵌套名称空间的惯例)

下面的代码片段显示了如何专门化
std::tr1::unordered\u映射
boost::const_string
void*
类似于
std::string
的散列方式

#include <boost/const_string/const_string.hpp>    
typedef class boost::const_string<char> csc;

namespace std
{
namespace tr1
{
template <>
struct hash<csc> {
public:
    size_t operator()(const csc & x) const {
        return std::_Hash_impl::hash(x.data(), x.size());
    }
};
}
}

typedef std::tr1::unordered_map<csc, void*> Map;
typedef Map::value_type Dual; ///< Element Type.
#包括
typedef类boost::const_字符串csc;
名称空间标准
{
名称空间tr1
{
模板
结构散列{
公众:
大小\u t运算符()(常量csc&x)常量{
返回std::_Hash_impl::Hash(x.data(),x.size());
}
};
}
}
typedef std::tr1::无序映射;
typedef映射::value_type Dual;//<元素类型。

有没有一种方法可以使用私有副本构造函数扩展用户定义类型的std::hash?还有,有没有一种方法可以用一个操作符()来扩展它,该操作符接受一个const ref而不是val?模板专门化有什么问题吗?您不需要获取对象的副本(通过引用传递),因此没有问题——运算符()可以获取常量ref或值,随您所需。看看Phil Nash的答案,它将对象作为常量ref。
#include <boost/const_string/const_string.hpp>    
typedef class boost::const_string<char> csc;

namespace std
{
namespace tr1
{
template <>
struct hash<csc> {
public:
    size_t operator()(const csc & x) const {
        return std::_Hash_impl::hash(x.data(), x.size());
    }
};
}
}

typedef std::tr1::unordered_map<csc, void*> Map;
typedef Map::value_type Dual; ///< Element Type.