У меня есть следующая проблема, из-за которой я не могу найти решение. Конечно, может быть, что решение вообще не существует, но я бы хотел попробовать, прежде чем сдаться.Внутренняя область перечисления, функция хэша и член данных unordered_set
Прежде всего, фрагмент кода, который компилируется без ошибок:
#include <unordered_set>
#include <memory>
struct S {
enum class E: unsigned int { FOO = 0, BAR };
};
namespace std
{
template<>
struct hash<S::E> {
using argument_type = S::E;
using underlying_type = std::underlying_type<argument_type>::type;
using result_type = std::size_t;
result_type operator()(argument_type const &s) const noexcept {
const underlying_type us = static_cast<underlying_type>(s);
hash<underlying_type> hfn;
return hfn(us);
}
};
}
int main() {
std::unordered_set<S::E> set;
}
С помощью этого кода в виду, я оказался с требованием имея unordered_set
в качестве члена данных S
или, по крайней мере, производный класс. Возможный рабочий раствор добавить добавить следующие строки после того, как std
пространства имен было закрыто:
struct D: public S {
std::unordered_set<S::E> set;
};
Другого возможным решения, может быть (я не пробовал) использовать незаданное перечисление. Во всяком случае, первая попытка я сделал было изменить определение struct S
как это следующим образом:
struct S {
enum class E: unsigned int { FOO = 0, BAR };
std::unordered_set<E> set;
};
Это заканчивается ошибкой, потому что (если я правильно понял проблему) unordered_set
требует специализированной hash
функции. Во всяком случае, последний требует, чтобы объявление было объявлено как минимум S::E
, поэтому его недостаточно для замены двух частей кода.
Здесь первая часть журнала ошибок (поскольку это очень долго):
In file included from /usr/include/c++/5/bits/hashtable.h:35:0,
from /usr/include/c++/5/unordered_set:47,
from main.cpp:1:
/usr/include/c++/5/bits/hashtable_policy.h: In instantiation of ‘struct std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> >’:
/usr/include/c++/5/type_traits:137:12: required from ‘struct std::__and_<std::__is_fast_hash<std::hash<S::E> >, std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> > >’
/usr/include/c++/5/type_traits:148:38: required from ‘struct std::__not_<std::__and_<std::__is_fast_hash<std::hash<S::E> >, std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> > > >’
/usr/include/c++/5/bits/unordered_set.h:95:63: required from ‘class std::unordered_set<S::E>’
main.cpp:6:27: required from here
/usr/include/c++/5/bits/hashtable_policy.h:85:34: error: no match for call to ‘(const std::hash<S::E>) (const S::E&)’
noexcept(declval<const _Hash&>()(declval<const _Key&>()))>
^
In file included from /usr/include/c++/5/bits/move.h:57:0,
from /usr/include/c++/5/bits/stl_pair.h:59,
from /usr/include/c++/5/utility:70,
from /usr/include/c++/5/unordered_set:38,
from main.cpp:1:
/usr/include/c++/5/type_traits: In instantiation of ‘struct std::__not_<std::__and_<std::__is_fast_hash<std::hash<S::E> >, std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> > > >’:
/usr/include/c++/5/bits/unordered_set.h:95:63: required from ‘class std::unordered_set<S::E>’
main.cpp:6:27: required from here
/usr/include/c++/5/type_traits:148:38: error: ‘value’ is not a member of ‘std::__and_<std::__is_fast_hash<std::hash<S::E> >, std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> > >’
: public integral_constant<bool, !_Pp::value>
^
In file included from /usr/include/c++/5/unordered_set:48:0,
from main.cpp:1:
/usr/include/c++/5/bits/unordered_set.h: In instantiation of ‘class std::unordered_set<S::E>’:
main.cpp:6:27: required from here
/usr/include/c++/5/bits/unordered_set.h:95:63: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<S::E> >, std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> > > >’
typedef __uset_hashtable<_Value, _Hash, _Pred, _Alloc> _Hashtable;
^
/usr/include/c++/5/bits/unordered_set.h:102:45: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<S::E> >, std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> > > >’
typedef typename _Hashtable::key_type key_type;
Обычно, в таком случае, я могу решить что-то вроде вперед декларации, как один в приведенном ниже примере :
struct B;
struct A { B *link; };
struct B { A *link; };
к сожалению, я не был в состоянии сделать что-то подобное с перечислимого вложенной в структуры, и именно поэтому я начал этот вопрос. Можно ли решить эту проблему, чтобы избежать определения производного класса D
, или получение в этом случае единственного жизнеспособного решения?
'enum class S_E ...; struct S {typedef S_E E;}; 'Всегда используйте' S :: E' почти везде, но 'S_E', где вам нужно работать с круговой зависимостью. –