我想声明如下:
class A {
std::unordered_set<A> set;
};
Run Code Online (Sandbox Code Playgroud)
我知道我需要 A 的哈希函数,但我认为这不是真正的问题。问题在于 unordered_set 的构造函数会犹豫,因为 A 是不完整类型。A 的前向声明并不能解决这个问题,但我不确定还有什么可能。
至于最小可重现的例子......
class A;
template <>
struct std::hash<A> {
// declare, but don't define, because A isn't defined yet
size_t operator()( const A& ) const;
};
class A {
public:
bool operator==( const A& ) const { return true; }
std::unordered_set<A> set;
};
inline size_t std::hash<A>::operator()( const A& ) const { return 0; }
Run Code Online (Sandbox Code Playgroud)
有什么办法可以做到这一点吗unordered_set<A*>?
使用 gcc 8.3.1 (C++14),我得到:
/usr/include/c++/8/ext/aligned_buffer.h: In instantiation of struct __gnu_cxx::__aligned_buffer<A>:
/usr/include/c++/8/bits/hashtable_policy.h:234:43: required from struct std::__detail::_Hash_node_value_base<A>
/usr/include/c++/8/bits/hashtable_policy.h:265:12: required from struct std::__detail::_Hash_node<A, true>
/usr/include/c++/8/bits/hashtable_policy.h:2038:49: required from struct std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<A, true> > >
/usr/include/c++/8/bits/hashtable.h:173:11: required from class std::_Hashtable<A, A, std::allocator<A>, std::__detail::_Identity, std::equal_to<A>, std::hash<A>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, true, true> >
/usr/include/c++/8/bits/unordered_set.h:100:18: required from class std::unordered_set<A>
/usr/include/c++/8/ext/aligned_buffer.h:91:28: error: invalid application of sizeof to incomplete type
: std::aligned_storage<sizeof(_Tp), __alignof__(_Tp)>
Run Code Online (Sandbox Code Playgroud)
为了拥有self的成员容器,容器类型必须支持不完整元素类型。这是因为类型本身的成员声明是不完整的。std::unordered_set不支持不完整的元素,因此不可能有std::unordered_set<A>.
间接是许多问题的解决方案,就像这个问题一样。std::unordered_set<std::unique_ptr<A>>例如,你可以有。
或者,如果可能的话,您可以定义自定义集类型,例如基于std::vector保持元素排序的类型。std::vector确实允许不完整的元素类型。