c++ - unordered_set<Foo> 作为 Foo 的数据成员?

标签 c++ unordered-set

正如标题所说,我正在尝试使用一个包含 Foo 类对象的 unordered_set 作为 Foo 类的数据成员。这在 C++ 中可能吗?

我有这个代码:

#include <unordered_set>
using namespace std;

struct FooHash;

class Foo {
public:
    int id;
    unordered_set<Foo, FooHash> foos; // error here
    bool operator==(const Foo& foo) {
        return id == foo.id;
    }
};

struct FooHash {
    size_t operator()(const Foo& foo) const {
        return foo.id;
    }
};

int main() {
    Foo f;
    unordered_set<Foo, FooHash> foos;
    return 0;
}

但它抛出以下错误:

In file included from /usr/include/c++/6.3.1/bits/hashtable.h:35:0,
                 from /usr/include/c++/6.3.1/unordered_set:47,
                 from main.cpp:1:
/usr/include/c++/6.3.1/bits/hashtable_policy.h: In instantiation of ‘struct std::__detail::__is_noexcept_hash<Foo, FooHash>’:
/usr/include/c++/6.3.1/type_traits:143:12:   required from ‘struct std::__and_<std::__is_fast_hash<FooHash>, std::__detail::__is_noexcept_hash<Foo, FooHash> >’
/usr/include/c++/6.3.1/type_traits:154:38:   required from ‘struct std::__not_<std::__and_<std::__is_fast_hash<FooHash>, std::__detail::__is_noexcept_hash<Foo, FooHash> > >’
/usr/include/c++/6.3.1/bits/unordered_set.h:95:63:   required from ‘class std::unordered_set<Foo, FooHash>’
main.cpp:9:33:   required from here
/usr/include/c++/6.3.1/bits/hashtable_policy.h:85:34: error: no match for call to ‘(const FooHash) (const Foo&)’
  noexcept(declval<const _Hash&>()(declval<const _Key&>()))>
           ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/6.3.1/bits/move.h:57:0,
                 from /usr/include/c++/6.3.1/bits/stl_pair.h:59,
                 from /usr/include/c++/6.3.1/utility:70,
                 from /usr/include/c++/6.3.1/unordered_set:38,
                 from main.cpp:1:
/usr/include/c++/6.3.1/type_traits: In instantiation of ‘struct std::__not_<std::__and_<std::__is_fast_hash<FooHash>, std::__detail::__is_noexcept_hash<Foo, FooHash> > >’:
/usr/include/c++/6.3.1/bits/unordered_set.h:95:63:   required from ‘class std::unordered_set<Foo, FooHash>’
main.cpp:9:33:   required from here
/usr/include/c++/6.3.1/type_traits:154:38: error: ‘value’ is not a member of ‘std::__and_<std::__is_fast_hash<FooHash>, std::__detail::__is_noexcept_hash<Foo, FooHash> >’
     : public integral_constant<bool, !_Pp::value>

向前声明这两个类并在之后声明方法给出了这两个错误:

In file included from /usr/include/c++/6.3.1/unordered_set:44:0,
                 from main.cpp:1:
/usr/include/c++/6.3.1/ext/aligned_buffer.h: In instantiation of ‘struct __gnu_cxx::__aligned_buffer<Foo>’:
/usr/include/c++/6.3.1/bits/hashtable_policy.h:246:43:   required from ‘struct std::__detail::_Hash_node_value_base<Foo>’
/usr/include/c++/6.3.1/bits/hashtable_policy.h:277:12:   required from ‘struct std::__detail::_Hash_node<Foo, true>’
/usr/include/c++/6.3.1/bits/hashtable_policy.h:1894:60:   required from ‘struct std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<Foo, true> > >’
/usr/include/c++/6.3.1/bits/hashtable.h:170:11:   required from ‘class std::_Hashtable<Foo, Foo, std::allocator<Foo>, std::__detail::_Identity, std::equal_to<Foo>, FooHash, 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++/6.3.1/bits/unordered_set.h:96:18:   required from ‘class std::unordered_set<Foo, FooHash>’
main.cpp:12:37:   required from here
/usr/include/c++/6.3.1/ext/aligned_buffer.h:85:34: error: invalid application of ‘sizeof’ to incomplete type ‘Foo’
     : std::aligned_storage<sizeof(_Tp), std::alignment_of<_Tp>::value>
                                  ^
/usr/include/c++/6.3.1/ext/aligned_buffer.h:85:34: error: invalid application of ‘sizeof’ to incomplete type ‘Foo’
/usr/include/c++/6.3.1/ext/aligned_buffer.h: In instantiation of ‘void* __gnu_cxx::__aligned_buffer<_Tp>::_M_addr() [with _Tp = Foo]’:
/usr/include/c++/6.3.1/ext/aligned_buffer.h:110:41:   required from ‘_Tp* __gnu_cxx::__aligned_buffer<_Tp>::_M_ptr() [with _Tp = Foo]’
/usr/include/c++/6.3.1/bits/hashtable_policy.h:250:34:   required from ‘_Value* std::__detail::_Hash_node_value_base<_Value>::_M_valptr() [with _Value = Foo]’
/usr/include/c++/6.3.1/bits/hashtable_policy.h:1971:36:   required from ‘void std::__detail::_Hashtable_alloc<_NodeAlloc>::_M_deallocate_node(std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type*) [with _NodeAlloc = std::allocator<std::__detail::_Hash_node<Foo, true> >; std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type = std::__detail::_Hash_node<Foo, true>]’
/usr/include/c++/6.3.1/bits/hashtable_policy.h:1984:22:   required from ‘void std::__detail::_Hashtable_alloc<_NodeAlloc>::_M_deallocate_nodes(std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type*) [with _NodeAlloc = std::allocator<std::__detail::_Hash_node<Foo, true> >; std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type = std::__detail::_Hash_node<Foo, true>]’
/usr/include/c++/6.3.1/bits/hashtable.h:1901:7:   required from ‘void std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::clear() [with _Key = Foo; _Value = Foo; _Alloc = std::allocator<Foo>; _ExtractKey = std::__detail::_Identity; _Equal = std::equal_to<Foo>; _H1 = FooHash; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, true, true>]’
/usr/include/c++/6.3.1/bits/hashtable.h:1227:12:   required from ‘std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::~_Hashtable() [with _Key = Foo; _Value = Foo; _Alloc = std::allocator<Foo>; _ExtractKey = std::__detail::_Identity; _Equal = std::equal_to<Foo>; _H1 = FooHash; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, true, true>]’
/usr/include/c++/6.3.1/bits/unordered_set.h:126:7:   required from here
/usr/include/c++/6.3.1/ext/aligned_buffer.h:99:36: error: using invalid field ‘__gnu_cxx::__aligned_buffer<_Tp>::_M_storage’
         return static_cast<void*>(&_M_storage);

标准中似乎不允许使用不完整类型的容器。我想尝试使用指针,但是 operator== 不能为指针操作数重载。有什么解决方法吗?

最佳答案

在将它们用作 unordered_set 的模板参数之前,您需要完全定义您的类.同时 Foo 期间无法完全定义它是自己的定义,但它的指针类型是。您可以替换 Foounique_ptr<Foo>很容易解决这个问题。

#include <memory>
#include <unordered_set>

// Forward declaration
class Foo;

// Declare classes
struct FooHash {
    size_t operator()(const std::unique_ptr<Foo>& foo) const;
};

class Foo {
public:
    int id;
    std::unordered_set<std::unique_ptr<Foo>, FooHash> foos;
};

// Method implementations
size_t FooHash::operator()(const std::unique_ptr<Foo>& foo) const {
    return foo->id;
}

关于c++ - unordered_set<Foo> 作为 Foo 的数据成员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42516582/

相关文章:

c++ - sqlite3_wal_checkpoint_v2 总是返回 SQL_BUSY

c++ - 引用变量在下一行程序执行后显示未定义的行为

c++ - Qt 的 std::unordered_set 模拟/对应

c++ - 具有自身无序集合的类

c++ - 当子类定义新的成员变量时,我可以避免 dynamic_cast 吗?

c++ - 隐式 “using namespace std” 没有写在源代码中

C++ STL 容器中的 NULL 指针

c++ - 在 boost::unordered_set 字符串中使用 Lambda 函数 - 不区分大小写

c++ - 制作空白输出文件的程序