为什么在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 模式下拒绝它,但即使在 C++20 模式下,clang 也会拒绝它。
查看汇编器输出,f总是返回0,因此它忽略了Derived传递给的任何潜在的实际数据f。
这是 UB,还是在 C++20 中合法,如果是,为什么?
回答
它在 C++20 中是合法的。
[expr.static.cast]/4 :
如果表达式
E是具有第一个元素的聚合类型 ([dcl.init.aggr])并且存在从到 类型的隐式转换序列,则表达式可以显式转换为类型T[...] 。TxEx
[dcl.init.aggr]/2 :
聚合的元素是: [...] 对于类,按声明顺序的直接基类,后跟不是匿名联合成员的直接非静态数据成员 ([class.mem]),在声明顺序。
所以Derived是聚集,其第一个元素是Base,由于C ++ 20,它被允许创建从其第一元件的集合体。
此功能在P1975R0 “修复括号聚合初始化的措辞”中引入。
- 这是我在 C++20 中见过的最违反直觉的代码之一。聚合仍然是一个不可预测的混乱。
THE END
二维码