下面的代码片段演示了我最近在程序中遇到的一些实际问题:
#include<vector>
class A;
void f( const std::vector<A> & = {} );
有一个不完整的类
A
,以及一个采用 vector
中的 A
且默认值为空的函数声明。而且该函数甚至没有在任何地方被调用。
它在 GCC 和 Clang 14 中工作正常,但从 Clang 15 开始出现错误:
In file included from <source>:1:
/opt/compiler-explorer/clang-15.0.0/bin/../include/c++/v1/vector:540:52: error: arithmetic on a pointer to an incomplete type 'A'
{return static_cast<size_type>(__end_cap() - this->__begin_);}
~~~~~~~~~~~ ^
/opt/compiler-explorer/clang-15.0.0/bin/../include/c++/v1/vector:760:56: note: in instantiation of member function 'std::vector<A>::capacity' requested here
__annotate_contiguous_container(data(), data() + capacity(),
^
/opt/compiler-explorer/clang-15.0.0/bin/../include/c++/v1/vector:431:7: note: in instantiation of member function 'std::vector<A>::__annotate_delete' requested here
__annotate_delete();
^
<source>:5:32: note: in instantiation of member function 'std::vector<A>::~vector' requested here
void f( const std::vector<A> & = {} );
^
<source>:3:7: note: forward declaration of 'A'
class A;
^
是的,Clang 拒绝该程序是正确的。根据 vector.overview#4:
如果分配器满足分配器完整性要求,则在实例化
时可以使用不完整类型T
。vector
应在引用T
所产生的专业化的任何成员之前完成。vector
在默认参数中,您在
vector<A>
完成之前引用 A
的构造函数,因此程序格式不正确。
这里有一个 bug 报告(因无效而关闭)显示了类似的情况。底部的评论表明了为什么这可能在 Clang-15 中发生了变化。
libc++14 和 libc++15 之间的变化可能是向量移动构造函数变成了 constexpr,因此现在它被更早实例化。