为什么 C++20 允许此值向下转换(static_cast 为对象类型)?
Why is this value downcast (static_cast to object type) allowed in C++20?
令我惊讶的是,gcc 11.2 accepts this code,但仅限于 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
总是 returns 0
,因此它忽略了传递给 f
的任何潜在 Derived
的实际数据。
这是 UB,还是在 C++20 中合法,如果是,为什么?
在 C++20 中是合法的。
An expression E
can be explicitly converted to a type T
[...] if T
is an aggregate type ([dcl.init.aggr]) having a first element x
and there is an implicit conversion sequence from E
to the type of x
.
The elements of an aggregate are: [...] for a class, the direct base classes in declaration order, followed by the direct non-static data members ([class.mem]) that are not members of an anonymous union, in declaration order.
因此 Derived
是第一个元素为 Base
的聚合,并且自 C++20 起,允许从其第一个元素创建聚合。
此功能在P1975R0“修复括号聚合初始化的措辞”中引入。
令我惊讶的是,gcc 11.2 accepts this code,但仅限于 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
总是 returns 0
,因此它忽略了传递给 f
的任何潜在 Derived
的实际数据。
这是 UB,还是在 C++20 中合法,如果是,为什么?
在 C++20 中是合法的。
An expression
E
can be explicitly converted to a typeT
[...] ifT
is an aggregate type ([dcl.init.aggr]) having a first elementx
and there is an implicit conversion sequence fromE
to the type ofx
.
The elements of an aggregate are: [...] for a class, the direct base classes in declaration order, followed by the direct non-static data members ([class.mem]) that are not members of an anonymous union, in declaration order.
因此 Derived
是第一个元素为 Base
的聚合,并且自 C++20 起,允许从其第一个元素创建聚合。
此功能在P1975R0“修复括号聚合初始化的措辞”中引入。