Подтвердить что ты не робот

Можно ли использовать std:: hash для указателей на хэш-функцию?

Можно ли использовать тип С++ 11 std::hash для указателей на хэш-функцию? Существует частичная специализация hash, определенная как

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

но поскольку указатели функций отличаются от других типов указателей в С++ (например, они не могут быть добавлены к void*), я не уверен, можно ли использовать его для таких типов, как int(*)() или void(*)(int, int).

Разрешено ли это? Есть ли какая-либо конкретная формулировка в новой спецификации ISO, которая поддерживает или опровергает это?

Спасибо!

4b9b3361

Ответ 1

Отличный вопрос. Я не знаю ответа наверняка, и я счастлив отнестись к любому, кто лучше знает меня, но я думаю, что, хотя указатели функций не совпадают с указателями данных, они все же указывают на указатели: 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;

}

Мне было бы очень интересно, если у кого-нибудь есть ссылки на стандарт, чтобы поддержать это, хотя.

Ответ 2

Я нашел следующее:

17.6.3.4 Требования к хешированию

Тип H соответствует требованиям Хэша, если:

  • это тип объекта функции (20.8)

[...]

И тогда указанные 20.8 состояния:

Тип объекта функции - это тип объекта (3.9), который может быть типом постфиксное выражение в вызове функции (5.2.2, 13.3.1.1).228 A Объект функции является объектом типа объекта функции. В местах где можно было бы ожидать, чтобы указатель на функцию алгоритмический шаблон (статья 25), интерфейс указан для принятия объект функции. Это не только делает алгоритмические шаблоны указатели на функции, но также позволяет им работать с произвольными объектов функции.

Это как бы утверждает это назад... но утверждение не только делает алгоритмические шаблоны работать с указателями на функции... кажется подходящим для вашего вопроса.

Ответ 3

Это действительно интересно... Я столкнулся с этим вопросом, используя MSVС++. Я пытаюсь сделать это:

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-to-voidptr). Причина в том, что void * является указателем данных, а указатель функции - указателем на код.

До сих пор я пришел к выводу, что он не разрешен и не будет компилироваться на MSVС++.