Может ли C ++ 11 std::hash
тип будет использоваться для хеширования указателей на функции? Eсть 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 соответствует требованиям Hash, если:
[…]
- это тип объекта функции (20.8)
И затем, упомянутые 20,8 состояния:
Тип объекта функции — это тип объекта (3.9), который может быть типом
Постфиксное выражение в вызове функции (5.2.2, 13.3.1.1) .228 A
Функциональный объект — это объект типа функционального объекта. В местах
где можно было бы передать указатель на функцию
алгоритмический шаблон (п. 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-to-voidptr для деталей). Причина в том, что void * является указателем данных, а указатель функции — указателем кода.
Пока я пришел к выводу, что это не разрешено и не будет компилироваться в MSVC ++.