Я не уверен, что это ошибка НКУ компилятор или предполагаемое поведение 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
,
Это предполагаемое поведение или это законный кодекс?
Для большей ясности:
Увидеть эта ссылка к Bugzilla для компилятора GCC для получения дополнительной информации.
В настоящее время ошибка все еще не подтверждена. Я обновлю вопрос как можно скорее.
Ваш код является законным, хотя 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 не должен отклонять ваш код.
Других решений пока нет …