这段代码是否会产生物化的基纯右值,它应该编译吗?
Does this code result in a materialized base prvalue, and should it compile?
以下代码在 gcc 9.1 中编译 godbolt but not clang 8 godbolt:
class A {
protected:
~A() = default;
};
class B final : public A {
};
int main() {
auto b = B{};
}
Clang 的错误:
<source>:10:16: error: temporary of type 'A' has protected destructor
auto b = B{};
^
<source>:3:5: note: declared protected here
~A() = default;
^
哪个是正确的,为什么?
感谢评论中的澄清;
自 C++17 以来,B{}
是聚合的,即使它是从 A
派生的,因此将由无法访问 dtor
。所以 clang 拒绝编译是正确的。标准:
no virtual, private, or protected (since C++17) base classes
但是使用 ()
将按照标准说明工作。
基地的dtor
可以public也可以保护
A common guideline is that a destructor for a base class must be
either public and virtual or protected and nonvirtual
与 C++11 相比,表达式 B()
是 prvalue
,而 auto b = B();
是 move-construction 并且移动可能会被省略,在 C++17 中,没有移动。 prvalue
没有被移动。这是 value-initializing B()
并且完全等同于:
B();
是的,Clang 拒绝代码是正确的。
在 auto b = B{};
中我们有一个聚合初始化,它直接发生在 main
函数中。所以这个函数必须能够调用 B
子类型的析构函数,以防在初始化过程中发生异常。
引自 N4861(最后一个 C++20 草案),[dcl.init.aggr]/8:
The destructor for each element of class type is potentially invoked
from the context where the aggregate initialization occurs. [ Note:
This provision ensures that destructors can be called for
fully-constructed subobjects in case an exception is thrown. — end
note ]
为了完整起见,引用 [class.dtor]/15:
[...] A program is ill-formed if a destructor that is potentially
invoked is deleted or not accessible from the context of the
invocation.
以下代码在 gcc 9.1 中编译 godbolt but not clang 8 godbolt:
class A {
protected:
~A() = default;
};
class B final : public A {
};
int main() {
auto b = B{};
}
Clang 的错误:
<source>:10:16: error: temporary of type 'A' has protected destructor
auto b = B{};
^
<source>:3:5: note: declared protected here
~A() = default;
^
哪个是正确的,为什么?
感谢评论中的澄清;
自 C++17 以来,B{}
是聚合的,即使它是从 A
派生的,因此将由无法访问 dtor
。所以 clang 拒绝编译是正确的。标准:
no virtual, private, or protected (since C++17) base classes
但是使用 ()
将按照标准说明工作。
基地的dtor
可以public也可以保护
A common guideline is that a destructor for a base class must be either public and virtual or protected and nonvirtual
与 C++11 相比,表达式 B()
是 prvalue
,而 auto b = B();
是 move-construction 并且移动可能会被省略,在 C++17 中,没有移动。 prvalue
没有被移动。这是 value-initializing B()
并且完全等同于:
B();
是的,Clang 拒绝代码是正确的。
在 auto b = B{};
中我们有一个聚合初始化,它直接发生在 main
函数中。所以这个函数必须能够调用 B
子类型的析构函数,以防在初始化过程中发生异常。
引自 N4861(最后一个 C++20 草案),[dcl.init.aggr]/8:
The destructor for each element of class type is potentially invoked from the context where the aggregate initialization occurs. [ Note: This provision ensures that destructors can be called for fully-constructed subobjects in case an exception is thrown. — end note ]
为了完整起见,引用 [class.dtor]/15:
[...] A program is ill-formed if a destructor that is potentially invoked is deleted or not accessible from the context of the invocation.