The wording of [expr.unary.noexcept] changed in C++17.
Previously (n4140, 5.3.7 noexcept operator [expr.unary.noexcept]), my emphasis:
- The result of the noexcept operator is false if in a potentially-evaluated context the expression would contain
(3.1) a potentially-evaluated call to a function, member function, function pointer, or member function pointer that does not have a non-throwing exception-specification ([except.spec]), unless the call is a constant expression ([expr.const]) ...
Now1 (7.6.2.6 noexcept operator [expr.unary.noexcept]):
- The result of the noexcept operator is true unless the expression is potentially-throwing ([except.spec]).
And then in 14.5 Exception specifications [except.spec]:
- If a declaration of a function does not have a noexcept-specifier, the declaration has a potentially throwing exception specification unless ...
but the unless list of 14.5(3) doesn't list constexpr
, leaving it as potentially throwing...
1 a link to C++17 n4659 added by L.F. in a comment.
Test code
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;
used to print (with gcc 8.3):
true
false
both when compiled with -std=c++11 and -std=c++2a
However the same code prints now (with gcc 9.2):
false
false
both when compiled with -std=c++11 and -std=c++2a
Clang by the way is very consistent, since 3.4.1 and goes with:
false
false
- What is the right behavior per each spec?
- Was there a real change in the spec? If so, what is the reason for this change?
- If there is a change in the spec that affects or contradicts past behavior, would it be a common practice to emphasize that change and its implications? If the change is not emphasized can it imply that it might be an oversight?
- If this is a real intended change, was it considered a bug fix that should go back to previous versions of the spec, are compilers right with aligning the new behavior retroactively to C++11?
Side Note: the noexcept
deduction on a constexpr
function affects this trick.