20

C++11std::hash类型可以用来散列函数指针吗?有一个hash偏特化定义为

template <typename T> struct hash<T*>;

但由于函数指针与 C++ 中的其他指针类型不同(例如,它们不能强制转换为void*),所以我不确定将它用于诸如int(*)()或之类的类型是否安全void(*)(int, int)

这是允许的吗?新的 ISO 规范中是否有任何具体的措辞支持或反驳这一点?

谢谢!

4

3 回答 3

11

好问题。我不确定答案,我很乐意听从比我知识更好的人,但我的想法是,即使函数指针与数据指针不同,它们仍然是指针:所以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;

}

如果有人对标准有任何参考来支持这一点,我会非常感兴趣。

于 2013-11-01T03:14:50.817 回答
1

我发现了以下内容:

17.6.3.4 哈希要求

如果满足以下条件,则类型 H 满足哈希要求:

  • 它是一个函数对象类型(20.8)

[...]

然后,引用的 20.8 状态:

函数对象类型是一种对象类型 (3.9),它可以是函数调用 (5.2.2, 13.3.1.1) 中后缀表达式的类型。228 函数对象是函数对象类型的对象。在人们期望将指向函数的指针传递给算法模板的地方(第 25 条),接口被指定为接受函数对象。这不仅使算法模板与函数指针一起工作,而且使它们能够与任意函数对象一起工作。

它有点倒退......但该声明不仅使算法模板与指向函数的指针一起工作......似乎适合您的问题。

于 2013-11-08T04:17:17.380 回答
-1

这实际上很有趣......我在使用 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++ 上编译。

于 2015-04-22T12:39:47.543 回答