-
Notifications
You must be signed in to change notification settings - Fork 772
[dcl.constexpr] Modernize example of constexpr-usable functions #6484
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
718450a
to
3d9d38a
Compare
3d9d38a
to
1145c0e
Compare
constexpr int uninit() { | ||
struct { int a; } s; | ||
return s.a; // error: uninitialized read of \tcode{s.a} | ||
constexpr int stinit(int n) { // \tcode{stinit} is constexpr-usable, but \tcode{stinit} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The paragraph the example is attached to defines constexpr-suitable, so I think that's what you meant.
constexpr int stinit(int n) { // \tcode{stinit} is constexpr-usable, but \tcode{stinit} | |
constexpr int stinit(int n) { // \tcode{stinit} is constexpr-suitable, but \tcode{stinit} |
int r = 1; | ||
while (--n > 0) r *= x; | ||
return r; | ||
constexpr int uninit() { // \tcode{uninit} is constexpr-usable, but a program which calls |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
constexpr int uninit() { // \tcode{uninit} is constexpr-usable, but a program which calls | |
constexpr int uninit() { // \tcode{uninit} is constexpr-suitable, but a program which calls |
} | ||
return n; | ||
constexpr std::generator<int> iota(int n = 0) { | ||
while (true) co_yield n++; // error: \tcode{co_yield} cannot be used in a constexpr function |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this example can be improved.
[expr.const] bans co_await
and co_yield
,
but [dcl.constexpr]p3 (the paragraph the example is attached to)
bans a constexpr function that is a coroutine.
So I think it might better to use co_return
instead,
which isn't banned by [expr.const].
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is about constexpr
, not about [expr.const].
The focus should be on stuff that is ok/ill-formed because of [dcl.constexpr].
Having one (punchy) example of something that is ok by [dcl.constexpr] but ill-formed if invoked in a constant-expression context in all cases is fine. An unconditional throw-expression is good enough for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think "OK" in this example means constexpr-usable/constexpr-suitable. So perhaps we should only use the simple "OK".
constexpr int uninit() { // \tcode{uninit} is constexpr-usable, but a program which calls | ||
struct { int a; } s; // \tcode{uninit} in a constant expression is ill-formed | ||
return s.a; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
constexpr int uninit() { // \tcode{uninit} is constexpr-usable, but a program which calls | |
struct { int a; } s; // \tcode{uninit} in a constant expression is ill-formed | |
return s.a; | |
constexpr int uninit() { // OK, but never produces a core constant expression | |
struct { int a; } s; | |
return s.a; // erroneous behavior: uninitialized read of \tcode{s.a} |
Edit: In C++26, the UB is changed to EB.
}; | ||
struct Derived : virtual Base { | ||
constexpr Derived() = default; // error: constructor cannot be constexpr in a | ||
}; // class or struct with virtual base classes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"class or struct" -> "class"
("class" covers all of union, class, struct)
Fixes #5718.
As explained in the issue, the example has become largely noise because of how many restrictions have been lifted in
constexpr
functions. The intuition of most users is probably thatabs
,long_max
,prev
and others should beconstexpr
, unless proven otherwise. This shift in mentality calls for examples which demonstrate what isn't constexpr-usable, rather than what is.