TIL以下程序是合法的以及诸如此类的:
#include <vector>
struct Bar;
struct Foo
{
using BarVec = std::vector<Bar>::size_type;
};
struct Bar {};
int main()
{
Foo f;
}
如何? Bar
是一个不完整的类型,因此编译器无法知道std::vector<Bar>
是什么,或者它包含成员size_type
,或者成员size_type
是一种类型。
我能想出的唯一解释是,任何假设的专业化(可能)都必须已经在范围内导致size_type
具有与&#34; base&#中给出的含义不同的含义34;模板定义,size_type
不是依赖名称(这两个因素都有助于编译器的确定性)。
这里的法律理由是什么?
答案 0 :(得分:12)
我认为在实践中这可能有用,但从我可以看出这看起来像未定义的行为。来自草案C ++ 11标准17.6.4.8
[res.on.functions] :
特别是,在以下情况下效果未定义:
[...]
- 如果在实例化模板组件时将不完整类型(3.9)用作模板参数, 除非特别允许该组件。
虽然实例化模板组件似乎不是一个明确定义的术语。
我通过LWG defect 611来到这里,其中添加了:
除非特别允许该组件。
到上面子弹的末尾所以它现在写着:
如果在实例化模板组件时将不完整类型(3.9)用作模板参数,则除非特别允许该组件。
作为shared_ptr
的例外情况,因为上述引用与20.6.6.2
[util.smartptr.shared]中的引用相冲突:
shared_ptr的模板参数T可以是不完整类型。
另见N4371: Minimal incomplete type support for standard containers, revision 2。