【问题标题】:Re-defining std::hash template struct重新定义 std::hash 模板结构
【发布时间】:2016-05-19 03:13:26
【问题描述】:

通常,如果新类型需要哈希,则必须专门化 std::hash。我编写了一个测试哈希库,并希望将它用于标准库尚未专门化的所有类型。

我使用 gcc/4.9.3 和 clang/3.7.0 尝试了以下操作。令我惊讶的是,它确实有效。

#include <utility>
#include <functional>
#include <iostream>

namespace std {

template<typename T>
class hash
{
    public:
        size_t operator()(const T & obj)
        {
            return 99;
        }
};
}

int main(void)
{
    int i = 10;
    std::pair<int, int> pi{22,33};

    std::hash<int> hi;
    std::hash<std::pair<int, int>> hpi;

    std::cout << "Hash of int: " << hi(i) << "\n";
    std::cout << "Hash of int pair: " << hpi(pi) << "\n";
    return 0;
}

整数的哈希是整数本身(这是标准库版本),对的哈希是99。

那么两个问题。

  1. 为什么有效? std::hash 的模板版本应该已经被声明了。 (我唯一的猜测是它在更深的命名空间中,会被转发)

  2. 这是标准行为吗?

编辑:对问题 1 的回答 - 已声明 template&lt;typename T&gt; struct hash,但似乎未在任何地方定义。这就是为什么我可以定义它。

【问题讨论】:

  • 像往常一样,未定义的行为包括“似乎在工作”。
  • @T.C.因此想知道这是否是已定义的行为......

标签: c++ hash stl


【解决方案1】:

17.6.4.2.1 命名空间标准 [namespace.std]

1 如果 C++ 程序添加声明或定义,则其行为未定义 namespace stdnamespace std 内的命名空间,除非另有说明 指定的。程序可以为任何 标准库模板到namespace std 仅当声明 取决于用户定义的类型,并且专业化满足 原始模板的标准库要求,而不是 明确禁止。

由于您将已存在的通用模板重新定义为namespace std,因此您的行为未定义。这包括@T.C.在 cmets 中提到该程序运行良好。

【讨论】:

  • 我最初的困惑是因为我认为我正在重新定义某些东西(这会违反 ODR 并且不应该编译)。即使我实际上添加了一个定义,它仍然违反了这个规则。 (是的,我非常清楚未定义的行为有时仍然有效)。
猜你喜欢
  • 1970-01-01
  • 2014-01-08
  • 2016-06-19
  • 2013-05-03
  • 2014-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-05
相关资源
最近更新 更多