Приводит ли этот код к материализации базового значения и должен ли он компилироваться? - PullRequest
8 голосов
/ 07 июня 2019

Следующий код компилируется в gcc 9.1 godbolt , но не 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;
    ^

Что правильно и почему?

1 Ответ

2 голосов
/ 07 июня 2019

Спасибо за разъяснения в комментариях; Поскольку C ++ 17, B{} является агрегатным, даже если он получен из A, поэтому для агрегатного инициатора будет создан временный A пользователем, который не имеет доступа к dtor. Таким образом, Clang правильно отклонить компиляцию. Стандарт:

нет виртуальных, частных или защищенных (начиная с C ++ 17) базовых классов

Однако использование () будет работать, как говорит стандарт.

dtor базы может быть общедоступным или защищенным.

Общим правилом является то, что деструктор для базового класса должен быть общедоступные и виртуальные или защищенные и не виртуальные

см. Руководство стандарта

В отличие от C ++ 11, где выражение B() - это prvalue, а auto b = B(); - конструкция-ход, и движение, скорее всего, будет исключено. В C ++ 17 нет движения , prvalue не перемещен из. Это инициализирующее значение B() и в точности эквивалентное:

B();

Значения категорий в C ++ 17

Если этот код не скомпилируется в C ++ 17?

...