我想声明如下内容:
class A {
std::unordered_set<A> set;
};
我知道我需要一个散列函数,但我不认为这是真实的的问题。问题是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; }
有没有什么方法可以在没有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)>
1条答案
按热度按时间mmvthczy1#
为了拥有self的成员容器,容器类型必须支持不完整的元素类型。这是因为一个类型在它自己的成员声明中是不完整的。
std::unordered_set
不支持不完整的元素,所以不可能有std::unordered_set<A>
。间接法是许多问题的解决方案,就像它是这个问题一样。例如,您可以使用
std::unordered_set<std::unique_ptr<A>>
。或者,如果可能的话,您可以定义一个自定义的set类型,例如基于
std::vector
来保持元素的排序。std::vector
允许不完整的元素类型。