g++5 中 std::unordered_set 编译错误的不完整类型,在 clang++ 中编译

Posted

技术标签:

【中文标题】g++5 中 std::unordered_set 编译错误的不完整类型,在 clang++ 中编译【英文标题】:incomplete type for std::unordered_set compiling error in g++5, compiles in clang++ 【发布时间】:2015-05-08 18:42:34 【问题描述】:

考虑与上一个 SO 问题 C++ cyclic dependency confusion with adjacency list representation 相关的代码

#include <cstddef>
#include <unordered_set>

class Node;

class Hash 
public:
    std::size_t operator()(const Node &node) const;
;

class Node 
public:
    int data;
    std::unordered_set<Node, Hash> links;
;

inline size_t Hash::operator()(const Node &node) const 
    return node.data;


int main()



此代码在使用 g++4.9.2 或 g++5 时无法编译,但使用 clang++3.5 编译。

g++吐出的错误以

开头

error: invalid application of 'sizeof' to incomplete type 'Node' : std::aligned_storage&lt;sizeof(_Tp), std::alignment_of&lt;_Tp&gt;::value&gt;

问题:在声明std::unordered_set 时,Node 是否必须是完整类型?在这种情况下,看起来 g++ 或 clang++ 都是错误的。

PS:我知道这种情况可以通过使用std::shared_ptr&lt;Node&gt; 来避免,但是想了解上面代码中的行为。

【问题讨论】:

【参考方案1】:

实例化具有不完整类型的标准库容器是未定义的行为。 [res.on.functions]/1, 2.5:

1 在某些情况下(替换函数、处理函数、 用于实例化标准库模板的类型的操作 组件),C++ 标准库依赖于提供的组件 通过 C++ 程序。如果这些组件不符合他们的要求, 该标准对实施没有任何要求。

2 特别是,在以下情况下效果是不确定的:

[...] 如果在实例化模板组件时将不完整类型 (3.9) 用作模板参数,除非特别允许 该组件。

两种实现都是正确的。

目前有proposal为部分容器添加不完全类型支持,但仅限于vectorlistforward_list

【讨论】:

嗯,clang++ 甚至没有发出警告,clang++ -std=c++11 -Wall -Wextra -Wpedantic so.cpp _ +1:我看不出有什么可以反驳这个答案的。 @T.C.谢谢,当场。我从一篇相当古老的 C++ 文章 drdobbs.com/the-standard-librarian-containers-of-inc/184403814 中知道 std::vector 存在问题,但不知道现在标准明确禁止在任何地方使用不完整类型(除非特别允许)。 @vsoftco 它不是“无处不在”,就像标准容器内容一样。 @MattMcNabb [res.on.functions] 适用于任何地方。

以上是关于g++5 中 std::unordered_set 编译错误的不完整类型,在 clang++ 中编译的主要内容,如果未能解决你的问题,请参考以下文章

我的班级有一个 toString() 方法,我如何使用它在 std::unordered_set 中进行散列?

std :: unordered_set :: find - 仅为find()构造一个实例

在 std::unordered_set<const char *> 中找不到转换为 const char * 的 std::string

对于操作计数()。 std::set<void*> 或 std::unordered_set<void*> 哪个更快?

在 std::unordered_map 中使用模板键

如何在 vscode 中使用 C++20?