c++ 有没有一种方法可以声明一个包含自身的unordered_set的类?

kb5ga3dv  于 2023-07-01  发布在  其他
关注(0)|答案(1)|浏览(122)

我想声明如下内容:

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)>
mmvthczy

mmvthczy1#

为了拥有self的成员容器,容器类型必须支持不完整的元素类型。这是因为一个类型在它自己的成员声明中是不完整的。std::unordered_set不支持不完整的元素,所以不可能有std::unordered_set<A>
间接法是许多问题的解决方案,就像它是这个问题一样。例如,您可以使用std::unordered_set<std::unique_ptr<A>>
或者,如果可能的话,您可以定义一个自定义的set类型,例如基于std::vector来保持元素的排序。std::vector允许不完整的元素类型。

相关问题