Does this code result in a materialized base prvalue, and should it compile?

Jef*_*ett 8 c++ destructor language-lawyer compiler-generated c++17

The following code compiles in gcc 9.1 godbolt but not clang 8 godbolt:

class A {
protected:
    ~A() = default;
};

class B final : public A {
};

int main() {
    auto b = B{};
}
Run Code Online (Sandbox Code Playgroud)

Clang's error:

<source>:10:16: error: temporary of type 'A' has protected destructor
    auto b = B{};
               ^
<source>:3:5: note: declared protected here
    ~A() = default;
    ^
Run Code Online (Sandbox Code Playgroud)

Which is correct and why?

Fed*_*dor 1

是的,Clang 拒绝代码是正确的。

\n

我们auto b = B{};有一个聚合初始化,它直接发生在main函数中。所以这个函数必须能够B在初始化过程中发生异常时调用子类型的析构函数。

\n

引用自 N4861(最后一个 C++20 草案),[dcl.init.aggr]/8

\n
\n

类类型的每个元素的析构函数都可能从发生聚合初始化的上下文中调用。[ 注意:\n此规定确保在抛出异常时可以为完全构造的子对象调用析构函数。\xe2\x80\x94 结束\n注]

\n
\n

为了完整起见,引用[class.dtor]/15

\n
\n

[...] 如果潜在调用的析构函数被删除或无法从调用的上下文访问,则程序是格式错误的。

\n
\n

  • 当然,我并不是说有什么不同,只是想让人们使用最好的“C++20”作为参考。 (2认同)