C++11std::hash
类型可以用来散列函数指针吗?有一个hash
偏特化定义为
template <typename T> struct hash<T*>;
但由于函数指针与 C++ 中的其他指针类型不同(例如,它们不能强制转换为void*
),所以我不确定将它用于诸如int(*)()
或之类的类型是否安全void(*)(int, int)
。
这是允许的吗?新的 ISO 规范中是否有任何具体的措辞支持或反驳这一点?
谢谢!
好问题。我不确定答案,我很乐意听从比我知识更好的人,但我的想法是,即使函数指针与数据指针不同,它们仍然是指针:所以std::hash<T*>
应该应用部分专业化。
-pendantic
对于它的价值,即使在 g++ 4.8.1 和 clang 3.3 中,以下编译也没有警告,并且按预期工作:
#include <functional>
#include <iostream>
void func1(int) {}
void func2(int) {}
int main()
{
typedef void (*func_type) (int);
std::hash<func_type> hash;
std::cout << hash(func1) << std::endl;
std::cout << hash(func2) << std::endl;
}
如果有人对标准有任何参考来支持这一点,我会非常感兴趣。
我发现了以下内容:
17.6.3.4 哈希要求
如果满足以下条件,则类型 H 满足哈希要求:
- 它是一个函数对象类型(20.8)
[...]
然后,引用的 20.8 状态:
函数对象类型是一种对象类型 (3.9),它可以是函数调用 (5.2.2, 13.3.1.1) 中后缀表达式的类型。228 函数对象是函数对象类型的对象。在人们期望将指向函数的指针传递给算法模板的地方(第 25 条),接口被指定为接受函数对象。这不仅使算法模板与函数指针一起工作,而且使它们能够与任意函数对象一起工作。
它有点倒退......但该声明不仅使算法模板与指向函数的指针一起工作......似乎适合您的问题。
这实际上很有趣......我在使用 MSVC++ 时遇到了这个问题。我想做的是:
static std::unordered_map<Fun, std::string> FunctionMap()
{
static std::unordered_map<Fun, std::string> map;
return map;
}
带有 Fun 的函数指针类型。
在编译期间,我收到以下错误:
error C2338: The C++ Standard doesn't provide a hash for this type.
....
_Kty=int (__thiscall Testje::* )(int,int)
在之前的尝试中,我尝试将函数指针强制转换为void*
,这是不允许的并且无法编译(请参阅:https ://isocpp.org/wiki/faq/pointers-to-members#cant-cvt-memfnptr-到-voidptr了解详细信息)。原因是 void* 是数据指针,而函数指针是代码指针。
到目前为止,我的结论是它是不允许的,它不会在 MSVC++ 上编译。