【问题标题】:Why is std::hash not specialised for std::reference_wrapper?为什么 std::hash 不专门用于 std::reference_wrapper?
【发布时间】:2015-05-01 14:21:17
【问题描述】:

我原以为会是这样,但在我的标准库实现 (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());
        }
    }; 
}

【问题讨论】:

  • 也许是因为如果你有一个引用包装器的容器,它是否应该散列引用或所指对象并不明显,并且提供标准的专业化将不得不选择一个并且这样做会混淆人们。由于未提供,因此您必须明确表达您的意图。
  • 如果不是参考,你会将reference_wrapper 散列在什么上面?它的唯一成员是get(),它返回一个T&amp;(以及执行相同操作的函数调用运算符)。它的存在几乎完全是为了允许将引用存储在标准容器中。
  • 指针,std::addressof(r.get()).
  • 是的,您可以添加一个散列函数来散列对象本身,这就是您在问题中所写的。但是,如果标准库中提供了其中一个,则会混淆人们对另一个的期望。他们是否可以自己编写另一个版本是无关紧要的。
  • 我认为智能指针的情况非常不同。要知道,引用是它所引用的对象的别名,引用包装器是类引用对象。另一方面,指针与它指向的对象明显不同,智能指针是一个类似指针的对象。很明显,智能指针的散列特化应该散列地址而不是对象。对于参考包装,它不是很清楚。

标签: c++ c++11 stdhash


【解决方案1】:

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

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

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

注意,如果您已经在散列对象并存储散列值,则可以通过将所有内容保存在 unordered_map 中来消除重复项。那么值标识和对象标识将是相同的。

【讨论】:

    猜你喜欢
    • 2021-12-31
    • 2013-04-09
    • 2017-11-10
    • 1970-01-01
    • 2015-07-05
    • 1970-01-01
    • 2012-09-08
    • 1970-01-01
    • 2021-04-05
    相关资源
    最近更新 更多