Я хотел бы сделать черту типа для проверки того, является ли конкретный тип хешируемым, используя стандартные экземпляры стандартных неупорядоченных контейнеров библиотеки, поэтому, если он имеет действительную специализацию для std::hash
. Я думаю, что это будет очень полезной функцией (например, для использования std::set
как безоткатного для std::unordered_set
в общем коде). Поэтому я, думая, что std::hash
не определен для каждого типа, начал делать следующее решение SFINAE:
template<typename T> std::true_type hashable_helper(
const T&, const typename std::hash<T>::argument_type* = nullptr);
template<typename T> std::false_type hashable_helper(...);
//It won't let me derive from decltype directly, why?
template<typename T> struct is_hashable
: std::is_same<decltype(hashable_helper<T>(std::declval<T>())),
std::true_type> {};
(Простите мои скромные способности SFINAE, если это не лучшее решение или даже неправильно.)
Но потом я узнал, что gcc 4.7 и VС++ 2012 определяют std::hash
для любого типа T
, просто static_assert
ing в неспециализированной версии. Но вместо компиляции условно они (а также clang 3.1 с использованием gcc 4.7 libstdС++) вызывают утверждение, приводящее к ошибке компиляции. Это кажется разумным, так как я думаю, что static_assert
не обрабатывается SFINAE (правильно?), Поэтому решение SFINAE кажется совсем не возможным. Это еще хуже для gcc 4.6
, который даже не имеет static_assert
в общем шаблоне std::hash
, но только не определяет его оператор ()
, что приводит к ошибке компоновщика при попытке (что всегда хуже, чем ошибка компиляции, и я не могу представить, каким образом можно преобразовать ошибку компоновщика в ошибку компилятора).
Итак, существует ли стандартно-совместимый и переносимый способ определения возвращаемого типа, если тип имеет допустимую специализацию std::hash
или, возможно, по крайней мере для библиотек static_assert
ing в общем шаблоне (каким-то образом преобразуя static_assert
ошибка в ошибке без SFINAE)?