Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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{};
}

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;
    ^

Which is correct and why?

like image 821
Jeff Garrett Avatar asked Jun 07 '19 16:06

Jeff Garrett


1 Answers

Thanks for the clarifications in the comments; Since C++17, B{} is aggregate even though it is derived from A, so a temporary A will be created for the aggregate init by the user which has no access to the dtor. So clang is correct in rejecting the compile. The standard:

no virtual, private, or protected (since C++17) base classes

However using () will work as the standard says.

The dtor of the base can be public or protected.

A common guideline is that a destructor for a base class must be either public and virtual or protected and nonvirtual

see the guideline of standard

In contrast with C++11, where the expression B() is a prvalue, and auto b = B(); is a move-construction and the move will likely get elided, In C++17, there is no move. The prvalue is not moved from. This is value-initializing B() and is exactly equivalent to:

B();

Value Categories in C++17

Should this code fail to compile in C++17?

like image 161
Oblivion Avatar answered Nov 15 '22 12:11

Oblivion