为什么std::hash没有针对std::reference_wrapper进行专门化处理?

12

我原以为这已经被实现了,但是在我的标准库实现(gcc-4.8.2)中找不到。

为什么std::hash没有专门为std::reference_wrapper进行特化?

#pragma once
#include <functional>

namespace std 
{
    template<typename T>
    struct hash<reference_wrapper<T>>
    {
        size_t operator()(const reference_wrapper<T>& r) const
        {
            return std::hash<T>()(r.get());
        }
    }; 
}

4
或许因为如果你有一个参考包装器的容器,很难确定它应该散列引用还是引用对象本身,而提供一个标准特化将不得不选择其中一个并因此使人们感到困惑。既然没有提供,那么就必须明确表达你的意图。 - Brian Bi
1
如果不使用引用,你会将reference_wrapper哈希到哪里?它唯一的成员是get(),它返回一个T&(以及执行相同操作的函数调用运算符)。它几乎完全存在于允许在标准容器中存储引用的情况下。 - Steve Lorimer
1
指针,即 std::addressof(r.get()) - Brian Bi
1
是的,而且您可以只需添加一个哈希函数来对对象本身进行哈希处理,这就是您在问题中编写的内容。但是,如果其中一个被提供在标准库中,它将会让期望另一个版本的人感到困惑。他们是否能自己编写另一个版本并不重要。 - Brian Bi
3
我认为智能指针的情况非常不同。你知道,引用是所引用对象的别名,而引用包装器是类似于引用的对象。另一方面,指针明显不同于其所指向的对象,而智能指针是类似于指针的对象。很明显,智能指针的哈希特化应该哈希地址而不是对象。对于引用包装器来说,情况并不那么清楚。 - Brian Bi
显示剩余2条评论
1个回答

3

std::reference_wrapper主要用于在默认复制值的实用程序中提供引用语义,例如std::bind

直接在容器中使用std::reference_wrapper本质上就像一个指针(除了它不可为空)。指针(和智能指针)的哈希遵循引用(即地址)语义。

当然,您始终可以提供自己的哈希函数。如果将其定义为所有指针和智能指针的模板,则T*可能是比reference_wrapper<T>更好的值类型选择。

请注意,如果您已经对对象进行了哈希并存储了哈希值,则通过将所有内容保留在unordered_map中,您可以消除重复项。然后,值标识和对象标识将相同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接