2011-11-30 73 views
16

有时它来实例化一个标准集装箱用一个不完整的类型得到递归结构是有益的:标准容器模板可以使用不完整类型实例化吗?

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; 
}; 

这往往会工作,因为容器没有那通型value_type或成员函数成员或返回任何value_type对象的价值。该标准似乎没有太多关于不完整的模板参数,但在C++ 11§17.6.4.8[lib.res.on.functions],“对其他函数的要求”中有一点:

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

这是否使上述构造非法,即使实例不在块范围内?这是否属于“用于实例化标准库模板组件的类型的操作”(也是17.6.4.8)?或者是一个库实现被禁止引发模板实例化,当所有特别需要的实例化成功时,这些模板实例化可能会因为不完整类型而失败?由于只有函数可以调用和实例化其他函数,因此将“类型...上的操作”限制为块范围中的那些函数似乎将成员函数的内容保留为比签名和成员的内容更严格的要求类定义。毕竟,在之前,multi_tree_node之间没有任何意义,直到类型完成为止。这扩展到std::unique_ptr,即使在块范围中使用时,它也明确支持不完整类型参数

编辑2:服务我没有困扰测试trie_node的例子 - 我甚至尝试过。这与@Ise链接的the article中的破坏示例相同。然而,虽然这篇文章似乎理所当然地认为“没有那样的东西可行”,但解决方案对我来说似乎很简单 - 的内部tree_node类应该是非成员模板,而不是成员非模板类。

无论如何,那篇文章确定了很好的设计意图,所以我猜想我在“功能需求”子标题下的挑剔只是这一点罢了。

+1

我没有在您发布的代码中看到任何不完整的类型? –

+1

@JohnDibling:'trie_node'在定义'next'时是不完整的。 –

+1

@JohnDibling在一个类的范围内,它是不完整的。 – Potatoswatter

回答

4

就个人而言,我觉得措辞实例在17.6.4.8/2是有点暧昧 ,但根据 this article, 标准的意图似乎不允许使用 标准集装箱递归类型。

相关提示,VC2005发出错误 class C { std::deque<C> x; };,而它编译 class C { std::vector<C> x; }; ...
然而,在我的理解,这个限制只是为了扩大 自由标准集装箱的实施。 所以Kerrek SB提到,可以有容器允许 递归数据结构,并且 Boost.Container 似乎提供这个设施。

10

这是我在试图解释:

标准简单地说,你必须这样做,即使任何给定的具体实施可能没有问题,支持这样的结构。但是,想象一下,如果有人想写一个“小矢量”优化,通过该优化矢量总是包含五个元素的空间。立即你会遇到麻烦,因为你有自我指涉类型。即使矢量根据值类型的大小采用了某种静态分支,这也是一个问题。

因此,为了不排除包含这些结构的实现,标准只是说您只能使用完整的类型。换句话说,大多数容器仅包含对值类型的引用或指针的事实是实现细节而不是标准要求。

只是为了澄清这一点:如果您定义了自己的自己的类模板,那么完全可以通过明确支持不完整类型的方式进行设计。该标准的一个例子是std::unique_ptr,它完全满意于不完整的类型参数T[](或甚至void)。

+0

+1个很好的例子,但我要等待一些从头开始的标准解释...我的代码肯定违反了引用的要求,但问题的另一部分是该要求是否或如何在函数/块范围之外应用。 (因为只有函数可以调用并实例化其他函数,所以这似乎将成员函数的内容保存为与签名和成员类定义的内容不同的标准。) – Potatoswatter

+0

“小向量”不是一个很好的示例;该标准不允许进行优化。 –

相关问题