不完整类型的新内容在包装在模板中时编译
new of incomplete type compiles when wrapped in template
考虑这段代码,有一个明显的编译错误:(1)
struct A;
struct B {
B() { new A(); } // error: allocation of incomplete type 'A'
};
使用unique_ptr
也无济于事:(2)
struct A;
struct B {
B() { std::make_unique<A>(); } // error: due to ~unique_ptr()
};
然后(令我非常惊讶)我发现,这将编译:(3)
struct A;
struct B {
B() { std::make_unique<A>(); }
};
struct A {}; // OK, when a definition is added **below**
然后我检查了一下,这是否也有助于new
- 不:(4)
struct A;
struct B {
B() { new A(); } // error: allocation of incomplete type 'A'
};
struct A {};
我认为这与template
有关,事实上:将new
包装在template
中确实可以编译:(5)
template <typename T>
T* my_new() { return new T(); } // OK, when wrapped in template
struct A;
struct B {
B() { my_new<A>(); }
};
struct A {};
为了完整起见,删除A
的定义会再次引发错误:(6)
template <typename T>
T* my_new() { return new T(); } // error: allocation of incomplete type 'A'
struct A;
struct B {
B() { my_new<A>(); }
};
// do note: definition of A removed
这是怎么回事?据我了解,编译器必须知道分配它的A
的大小/定义,因此仅仅声明它是不够的。此外,我认为,定义必须先于分配。
当直接使用new
时,这似乎是正确的(1,4)。但是当new
被包裹时,很明显我错了(2,3,5,6)。
到目前为止,我发现的可能解释是:
- 对已完成类型的检查将延迟到发生
template
实例化。我认为这是正确的,但就我而言,直接使用new A()
和调用my_new<A>()
几乎发生在同一个位置。所以这不能成为原因。右? - 使用不完整的类型作为
template
参数可能是未定义的行为。这是真的吗?即使启用所有警告,编译器也不会抱怨。比较 5 和 6 似乎也表明,编译器足够聪明,可以弄清楚,定义如下(因此实际上使类型完整)。
为什么 4 被认为是不正确的,而 5 编译(或者 5 只是虚假编译未定义的行为 [但 3 也必须有缺陷,对吧?
顺便说一句:使用 CLANG++-3.5.0 和 G++-4.9.2 进行测试
§14.6.4.1 [temp.point]/p1,8,强调我的:
1 对于函数模板专用化,成员函数模板 专用化,或成员函数或静态的专用化 类模板的数据成员(如果专用化是隐式的) 实例化,因为它是从另一个模板中引用的 专业化及其引用上下文取决于 模板参数,专业化的实例化点 是封闭专用化的实例化点。 否则,这种专业化的实例化点 紧跟在命名空间范围声明或定义之后 指专业化。
8 函数模板、成员函数模板的专用化, 或成员函数或静态数据的成员类模板可以 在一个翻译单元中有多个实例化点,以及 除了上述实例化点外,对于任何 这种专业化在 翻译单元,翻译单元的末尾也被认为是一个 实例化点。类模板的专用化在 翻译单元中的大多数实例化点。一个 任何模板的专用化都可以在 多个翻译单元。如果两个不同的实例化点 根据模板赋予模板专业化不同的含义 定义规则(3.2),程序格式不正确,无诊断 必填。
my_new<A>
的实例化有两个点,一个在B
定义的末尾,一个在翻译单元的末尾。由于这两点将导致不同的含义(对于片段 3 和 5),因此程序的 NDR 格式不正确(即,它具有未定义的行为)。
- 二叉排序树无法编译
- 线程构造函数周围的可变参数模板包装器无法编译
- 无法使用两个包装不同下一层的ssl_stream编译代码
- 将代码块包装为编译时值
- 将 boost::时序机制包装成类编译错误?
- 使用 Python 包装器编译 VTK
- f freeBSD上的r羽毛包装编译错误(G )
- 编译 TCL-DLL 包装器时出现的问题
- 用于测试Poco HTTPServer的包装程序handleRequest未编译
- 在Xubuntu上使用SOCI(sql包装器),简单的程序在编译时失败
- 不完整类型的新内容在包装在模板中时编译
- numpyarrayobject.h 在 Windows 中编译 SWIG python 包装器时未被 MinGW
- 在Windows中为python编译SWIG包装器
- 编译包装器时出现SWIG [C++ to Lisp(CFFI)]错误
- 无法为c++python扩展编译swig生成的包装
- 当<T> T 没有复制构造函数时,std::queue 的虚拟包装器不会编译
- Boost图形包装器编译错误
- 使用ctypes为librsync编写python包装器.我应该如何编译librsync以在所有系统上工作
- 在编译时自动用注释包装C/ c++函数
- 在为 OpenCV 的 C++ createTrackbar 运行 C 包装器时出现编译分段错误(核心转储)