为什么在c++ 20中允许这个值向下转换(static_cast到对象类型)?



令我惊讶的是,gcc 11.2接受这些代码,但仅在c++ 20模式下:

struct Base {};
struct Derived : Base { int i; };
int f(Base& b) { return static_cast<Derived>(b).i; }
//                                  ^~~~~~~ oops, forgot the `&`

同样,MSVC 19.29在c++ 20模式下接受它,在c++ 17模式下拒绝它,但是clang即使在c++ 20模式下也拒绝它。

查看汇编器输出,f总是返回0,因此它忽略了传递给f的任何潜在Derived的实际数据。

这是UB,或者在c++ 20中是合法的,如果是,为什么?

在c++ 20中是合法的。

[expr.static.cast]/4:

表达式E可以显式转换为类型T[…]如果T是一个聚合类型([dcl.init.aggr]),其第一个元素为x,并且存在从Ex类型的隐式转换序列。

[dcl.init.aggr]/2:

聚合的元素是:[…]对于一个类,直接的基类按声明顺序排列,然后是直接的非静态数据成员([class.mem]),它们不是匿名联合的成员,按声明顺序排列。

所以Derived是一个第一个元素是Base的聚合,从c++ 20开始,允许从它的第一个元素创建一个聚合。

此特性在P1975R0"修正括号聚合初始化"的措辞"中引入。

最新更新