Формулировка [expr.unary.noexcept] изменена в C ++ 17.
Ранее (n4140, 5.3.7 оператор noexcept [expr.unary.noexcept]), мой акцент:
- Результатом оператора noexcept будет false, если в потенциально оцениваемом контексте выражение будет содержать
# P3 #
Теперь 1 (7.6.2.6 оператор noexcept [expr.unary .noexcept]):
- Результатом оператора noexcept является истина, если выражение не является потенциально бросающим ([except.spec]).
А затем в 14.5 Спецификации исключений [except.spec]:
- Если объявление функции не имеет спецификатора noexcept-спецификатора, объявление имеет потенциально генерирующую спецификацию исключения, если ...
но if list из 14.5 (3) не перечисляет constexpr
, оставляя его как потенциально бросающий ...
1 ссылка на C ++ 17 n4659, добавленный LF в комментарии.
Тестовый код
constexpr int f(int i) { return i; }
std::cout << boolalpha << noexcept(f(7)) << std::endl;
int a = 7;
std::cout << boolalpha << noexcept(f(a)) << std::endl;
используется для печати (с gcc 8.3):
true
false
оба при компиляции с -std = c ++ 11 и -std = c ++ 2a
Однако теперь печатается тот же код (с gcc 9.2):
false
false
оба при компиляции с -std = c ++ 11 и -std = c ++ 2a
Между прочим, Clang очень согласован, начиная с 3.4.1 и работает с:
false
false
- Как правильно поступать в соответствии с каждой спецификацией?
- Произошло ли реальное изменение в спецификации? Если да, то в чем причина этого изменения?
- Если в спецификации есть изменение, которое влияет или противоречит прошлому поведению, будет ли обычной практикой подчеркивать это изменение и его последствия? Если изменение не выделено, может ли оно означать, что это может быть недосмотр?
- Если это действительно запланированное изменение, считалось ли это исправлением ошибки, которое должно вернуться к предыдущим версиям спецификации, правильно ли компиляторы согласовали новое поведение задним числом с C ++ 11?
Примечание: вычет noexcept
функции constexpr
влияет на этот трюк .