有没有办法声明一个包含自身 unordered_set 的类?

use*_*566 2 c++

我想声明如下:

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)

eer*_*ika 5

为了拥有self的成员容器,容器类型必须支持不完整元素类型。这是因为类型本身的成员声明是不完整的。std::unordered_set不支持不完整的元素,因此不可能有std::unordered_set<A>.

间接是许多问题的解决方案,就像这个问题一样。std::unordered_set<std::unique_ptr<A>>例如,你可以有。

或者,如果可能的话,您可以定义自定义集类型,例如基于std::vector保持元素排序的类型。std::vector确实允许不完整的元素类型。

  • @HolyBlackCat [res.on.functions] 通常不允许不完整的模板参数。允许它们的地方是例外。list、forward_list 和 vector 是唯一出现此类异常的容器。违反完整性要求是UB,因此不需要实现来诊断它。 (3认同)