Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 标准容器模板是否可以用不完整的类型实例化?_C++_Templates_Stl_Incomplete Type - Fatal编程技术网

C++ 标准容器模板是否可以用不完整的类型实例化?

C++ 标准容器模板是否可以用不完整的类型实例化?,c++,templates,stl,incomplete-type,C++,Templates,Stl,Incomplete Type,有时,实例化具有不完整类型的标准容器以获得递归结构非常有用: struct multi_tree_node { // Does work in most implementations std::vector< multi_tree_node > child; }; struct trie_node { // Does not work in most implementations std::map< char, trie_node > next; }

有时,实例化具有不完整类型的标准容器以获得递归结构非常有用:

struct multi_tree_node { // Does work in most implementations
    std::vector< multi_tree_node > child;
};

struct trie_node { // Does not work in most implementations
    std::map< char, trie_node > next;
};
struct multi_tree_node{//在大多数实现中都有效
std::vectorchild;
};
结构trie_节点{//在大多数实现中不起作用
std::mapnext;
};
这是因为容器没有类型为
value\u类型
的成员,也没有按值传递或返回任何
value\u类型
对象的成员函数。该标准似乎没有对不完整的模板参数做太多的说明,但在C++11§17.6.4.8[lib.res.on.functions]“其他函数的要求”中有一点:

特别是,在以下情况下,效果是未定义的:…如果在实例化模板组件时将不完整类型(3.9)用作模板参数,除非该组件特别允许

即使实例化不在块范围内,这是否会使上述构造非法?这是否属于“用于实例化标准库模板组件的类型上的操作”(也是17.6.4.8)?或者,当所有特定要求的实例化成功时,库实现是否禁止引发可能因不完整类型而失败的模板实例化

编辑:由于只有函数可以调用和实例化其他函数,因此将“类型上的操作…”限制在块范围内的操作似乎比签名和成员类定义的内容要求更严格。毕竟,在类型完成之前,对
多树节点执行任何操作都毫无意义。这扩展到了
std::unique_ptr
,它明确支持不完整的类型参数,即使在块范围中使用

edit2:我没有费心去测试
trie_节点
示例,这对我来说是一件好事,我以前甚至试过。这与@Ise链接中的破损示例相同。然而,尽管这篇文章似乎想当然地认为“这样的方法是行不通的”,但解决方案对我来说似乎很简单-
std::map
的内部
tree\u节点
类应该是非成员模板,而不是成员非模板类


无论如何,那篇文章很好地确立了设计意图,所以我想我对“功能需求”这一副标题下的挑剔仅此而已。

以下是我的解释:

标准只是说你不能这样做,即使任何特定的具体实现支持这样的构建可能没有问题。但是想象一下,例如,如果有人想写一个“小向量”优化,其中向量总是包含空间,比如说,五个元素。你马上就会遇到麻烦,因为你会有一个自我引用类型。即使向量根据值类型的大小采用某种静态分支,这也是一个问题

因此,为了不妨碍实现包含这样的构造,标准只是说您必须只使用完整类型。换句话说,大多数容器只包含对值类型的引用或指针这一事实是实现细节,而不是标准要求


只是为了澄清这一点:如果您定义了自己的类模板,那么完全有可能将其设计为显式支持不完整类型。标准中的一个例子是
std::unique_ptr
,它对不完整的类型参数
T[]
(甚至
void
)非常满意。

我个人觉得17.6.4.8/2中实例化的措辞有点夸张 模棱两可,但根据 , 该标准的意图似乎不允许使用递归数据类型 标准容器

在一个相关的注释中,VC2005为 类C{std::dequex;},当它编译时 类C{std::vectorx;}
不过,据我理解,这项限制只是为了扩大范围 自由实施标准容器。 正如Kerrek SB所提到的,可以有允许 递归数据结构,以及
似乎提供了此功能。

一般来说,使用不完整类型作为标准库组件的模板参数是不正确的。以下是:

如果在实例化模板组件或评估概念时使用不完整的类型([basic.types])作为模板参数,除非该组件特别允许

请注意,自c++17以来,已向
std::vector
授予显式权限,以允许不完整的类型。以下是:

如果分配器满足分配器完整性要求,则在实例化向量时可以使用不完整类型T。T应在引用向量的任何结果专门化成员之前完成


因此,在您的示例中,
multi_tree_node
格式良好,但是
trie_node
是UB。

我在您发布的代码中没有看到任何不完整的类型?@JohnDibling:
trie_node
在类自身范围内定义
next
@JohnDibling时不完整。相关:顺便说一句,它是
[17.4.3.6]
在C++03标准中,供感兴趣的人使用。另外,最好也添加段落所在的标记,在本例中,
[lib.res.on.functions]
+1个很好的示例,但我将等待一些从头开始的标准解释…我的代码肯定违反了引用的要求,但问题的另一部分是需求是否或如何应用于函数/块范围之外。(因为只有函数可以调用和实例化其他函数,这似乎使成员函数的内容与签名的内容保持不同的标准