【发布时间】:2019-10-22 07:13:47
【问题描述】:
以下简单哈希函数的代码无法编译
#include <cstddef>
#include <functional>
namespace {
struct Foo {
long i;
};
}
namespace std {
template<> struct hash<::Foo> {
size_t operator()(::Foo foo) const {
return hash<decltype(foo.i)>(foo.i);
}
};
}
我的 4.8.5 g++ 编译器发出这些消息:
$ g++ -std=c++11 a.cpp
a.cpp: In member function ‘std::size_t std::hash<{anonymous}::Foo>::operator()({anonymous}::Foo) const’:
a.cpp:13:47: error: no matching function for call to ‘std::hash<long int>::hash(long int&)’
return hash<decltype(foo.i)>(foo.i);
^
a.cpp:13:47: note: candidates are:
In file included from /usr/include/c++/4.8.2/bits/basic_string.h:3033:0,
from /usr/include/c++/4.8.2/string:52,
from /usr/include/c++/4.8.2/stdexcept:39,
from /usr/include/c++/4.8.2/array:38,
from /usr/include/c++/4.8.2/tuple:39,
from /usr/include/c++/4.8.2/functional:55,
from a.cpp:2:
/usr/include/c++/4.8.2/bits/functional_hash.h:107:3: note: constexpr std::hash<long int>::hash()
_Cxx_hashtable_define_trivial_hash(long)
^
/usr/include/c++/4.8.2/bits/functional_hash.h:107:3: note: candidate expects 0 arguments, 1 provided
/usr/include/c++/4.8.2/bits/functional_hash.h:107:3: note: constexpr std::hash<long int>::hash(const std::hash<long int>&)
/usr/include/c++/4.8.2/bits/functional_hash.h:107:3: note: no known conversion for argument 1 from ‘long int’ to ‘const std::hash<long int>&’
/usr/include/c++/4.8.2/bits/functional_hash.h:107:3: note: constexpr std::hash<long int>::hash(std::hash<long int>&&)
/usr/include/c++/4.8.2/bits/functional_hash.h:107:3: note: no known conversion for argument 1 from ‘long int’ to ‘std::hash<long int>&&’
$ fg
问题似乎是第一条错误消息中的引用调用,但我不明白为什么或如何解决它。
【问题讨论】:
-
仅供参考,
namespace std {};调用未定义的行为。你不应该扩展命名空间标准。 -
@Chipster 不完全是。 “只有当声明依赖于用户定义的类型并且特化满足原始模板的标准库要求并且未明确禁止时,程序才能将任何标准库模板的模板特化添加到
namespace std。” -
@Chipster 在这种情况下是合法的。您可以打开命名空间并为您的类型添加专业化。见:timsong-cpp.github.io/cppwp/n4659/namespace.std#1
-
@Brian,但添加其他内容是未定义的行为,除了模板。
-
@Chipster 但是 OP 正在做的正是合法的事情:为他们自己的类型添加一个标准模板的专业化。这是将您的类型与
std::hash网格化的方法。