C++ 具有无序_映射的相互依赖类型

C++ 具有无序_映射的相互依赖类型,c++,stl,circular-dependency,libstdc++,C++,Stl,Circular Dependency,Libstdc++,假设我想在条目之间保持一定的顺序 一张无序的地图。一种节省内存的方法似乎是在地图的条目之间保留一个链表。也就是说,我将使用节点定义为 struct节点{ int-val; typename std::无序映射::迭代器向上; }; 这是有效的C++吗?Clang和gcc不允许此节点为不完整类型。请参阅下面的完整错误消息。双方均接受以下内容: 模板 结构图{ 结构映射项{ 钥匙; 价值增值; 地图条目*prev,*next; }; 使用迭代器=映射项*; }; 结构节点{ int-val; Ma

假设我想在条目之间保持一定的顺序 一张无序的地图。一种节省内存的方法似乎是在地图的条目之间保留一个链表。也就是说,我将使用节点定义为

struct节点{
int-val;
typename std::无序映射::迭代器向上;
};

这是有效的C++吗?Clang和gcc不允许此节点为不完整类型。请参阅下面的完整错误消息。双方均接受以下内容:

模板
结构图{
结构映射项{
钥匙;
价值增值;
地图条目*prev,*next;
};
使用迭代器=映射项*;
};
结构节点{
int-val;
Map::迭代器up;
};
这里的规则是什么?为什么第一个不被接受,而第二个可以?在一个相关的例子中,出现了一个类似的问题,然而,对于这里应用的相同解释,无序的_映射必须包含一个没有任何间接寻址的值对象。即无序_图的定义应如下所示:

模板
类无序映射{
价值增值;
使用value_type=std::pair;
使用entry=std::tuple;
使用迭代器=条目*;
};
我不明白为什么无序的映射应该直接存储一个值。否则,, 正如我在上面给出的玩具示例结构图一样,没有依赖循环

In file included from /usr/include/c++/8/unordered_map:43,
                 from test.cpp:1:
/usr/include/c++/8/bits/stl_pair.h: In instantiation of ‘struct std::pair<const int, Node>’:
/usr/include/c++/8/ext/aligned_buffer.h:91:28:   required from ‘struct __gnu_cxx::__aligned_buffer<std::pair<const int, Node> >’
/usr/include/c++/8/bits/hashtable_policy.h:234:43:   required from ‘struct std::__detail::_Hash_node_value_base<std::pair<const int, Node> >’
/usr/include/c++/8/bits/hashtable_policy.h:280:12:   required from ‘struct std::__detail::_Hash_node<std::pair<const int, Node>, false>’
/usr/include/c++/8/bits/hashtable_policy.h:2027:49:   required from ‘struct std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<const int, Node>, false> > >’
/usr/include/c++/8/bits/hashtable.h:173:11:   required from ‘class std::_Hashtable<int, std::pair<const int, Node>, std::allocator<std::pair<const int, Node> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >’
/usr/include/c++/8/bits/unordered_map.h:105:18:   required from ‘class std::unordered_map<int, Node>’
test.cpp:5:32:   required from here
/usr/include/c++/8/bits/stl_pair.h:215:11: error: ‘std::pair<_T1, _T2>::second’ has incomplete type
       _T2 second;                /// @c second is a copy of the second object
           ^~~~~~
test.cpp:3:8: note: forward declaration of ‘struct Node’
 struct Node {
在/usr/include/c++/8/unordered_map:43中包含的文件中,
来自测试。cpp:1:
/usr/include/c++/8/bits/stl_pair.h:在“struct std::pair”的实例化中:
/usr/include/c++/8/ext/aligned_buffer.h:91:28:必须来自“struct\uu gnu\u cxx::\uu aligned_buffer”
/usr/include/c++/8/bits/hashtable_policy.h:234:43:从“结构std::_详细信息::_Hash_node_value_base”中需要
/usr/include/c++/8/bits/hashtable_policy.h:280:12:必须来自“struct std::u detail::_Hash_node”
/usr/include/c++/8/bits/hashtable_policy.h:2027:49:从“struct std::_细节::_hashtable_alloc”中需要
/usr/include/c++/8/bits/hashtable.h:173:11:从“class std::u hashtable”中需要
/usr/include/c++/8/bits/unordered_-map.h:105:18:class std::unordered_-map中的必填项
测试。cpp:5:32:从这里开始需要
/usr/include/c++/8/bits/stl_pair.h:215:11:错误:“std::pair::second”的类型不完整
_T2秒;///@c second是第二个对象的副本
^~~~~~
test.cpp:3:8:注意:“结构节点”的正向声明
结构节点{

struct节点{
int-val;
typename std::无序映射::迭代器向上;
};
<> > <>强> > < >强> > C++ 17标准的有效C++。提供不完整类型<代码>节点<代码>:<代码>:代码< >代码:STD::清单< /COD>和 STD::转发文件按最近接受的C++ 17有效,但未排序的映射仍然提供完整类型。
MSVC和libc++在值不完整的情况下运行良好,但这是因为它们超出了标准的要求。

无序映射中的迭代器不仅仅是指针。它必须包含足够的上下文来导航存储桶列表,这可能需要知道存储在其中的内容的大小。您的第二个类只使用指针作为迭代器,不需要完整的类描述。@1201programalm编译器所做的事情比在类型不是指针时停止要复杂得多。链接的问题解释了过程。为什么不使用
节点*
?@super这是一个很好的问题。重点是能够擦除“u”中的节点p'顺序而不需要额外的密钥散列。一旦您拥有无序的\u map::iterator作为句柄,您就可以非常快速地执行映射操作,甚至不需要密钥hash@super同样,要使该设计起作用,节点结构必须有一个键的副本(或指向它的指针)。这也不是理想的。但是,libstdc++是允许失败的还是一个bug?这不能回答代码是否正确。@FrançoisAndrieux这是一个很好的问题。我正在调查这种行为是否是规范的一部分