noexcept, наследующие конструкторы и недопустимое использование неполного типа, который фактически завершен

Я не уверен, что это ошибка НКУ компилятор или предполагаемое поведение noexcept,
Рассмотрим следующий пример:

struct B {
B(int) noexcept { }
virtual void f() = 0;
};

struct D: public B {
using B::B;
D() noexcept(noexcept(D{42})): B{42} { }
void f() override { }
};

int main() {
B *b = new D{};
}

Если noexcept удаляется, компилируется.
Во всяком случае, как и в примере, я получил эту ошибку от GCC v5.3.1:

test.cpp:8:31: error: invalid use of incomplete type ‘struct D’
D() noexcept(noexcept(D{42})): B{42} { }
^

Насколько я знаю, struct D не является неполным типом, но в утверждении участвуют наследующие конструкторы, и похоже, что компилятор фактически учитывает полноту базовой структуры B больше чем D,

Это предполагаемое поведение или это законный кодекс?

Для большей ясности:

  • Вот компиляция успешно с использованием лязг 3.7.1
  • Вот компиляция не удалась с помощью GCC 5.3.0

Увидеть эта ссылка к Bugzilla для компилятора GCC для получения дополнительной информации.
В настоящее время ошибка все еще не подтверждена. Я обновлю вопрос как можно скорее.

12

Решение

Ваш код является законным, хотя GCC утверждает иное. Обидно на это смешное заявление:

D() noexcept(noexcept(D{42}));

Самый внешний noexcept это нет, кроме спецификатора, основываясь на этом D::D() noexcept, если и только если его аргумент с постоянным выражением имеет значение true. Внутренний noexcept это нет, кроме оператора который проверяет во время компиляции, не вызывает ли его выражение аргумента, которое фактически не оценивается, никаких исключений. Так как D::D(int) не исключая (наследуется от B), это должно быть правдой.

cppreference.com явно отмечает, что использование оператора внутри спецификатора разрешено (выделение добавлено):

Оператор noexcept выполняет проверку во время компиляции, которая возвращает true, если объявлено, что выражение не выдает никаких исключений.

Его можно использовать в спецификаторе noexcept шаблона функции, чтобы объявить, что функция будет выдавать исключения для некоторых типов, но не для других.

Теперь класс должен быть рассмотрен полный в спецификаторе noexcept согласно §9.2.2 Стандарта (выделено жирным шрифтом):

Класс считается полностью определенным типом объекта (3.9) (или завершенным типом) при закрытии } из класса спецификатор. В классе член-спецификация, класс считается завершенным в течение тела функций, аргументы по умолчанию, используя декларированиеs введение наследующих конструкторов (12.9), Исключение-спецификацияs, а также скобки или равно-инициализаторs для нестатических членов данных (включая такие вещи во вложенных классах). В противном случае он считается неполным в своем классе член-спецификация.

§15.4.1 определяет Исключение-спецификация как следующая грамматика:

Исключение-спецификация:

  • Исключение динамически-спецификация

  • noexcept-спецификация

Поэтому GCC не должен отклонять ваш код.

12

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]