Skip to content

[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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 16 additions & 23 deletions source/declarations.tex
Original file line number Diff line number Diff line change
Expand Up @@ -879,33 +879,26 @@

\begin{example}
\begin{codeblock}
constexpr int square(int x)
{ return x * x; } // OK
constexpr long long_max()
{ return 2147483647; } // OK
constexpr int abs(int x) {
if (x < 0)
x = -x;
return x; // OK
constexpr int square(int x) { // OK
return x * x;
}
constexpr int constant_non_42(int n) { // OK
if (n == 42) {
static int value = n;
return value;
}
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
Copy link
Contributor

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].

}
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}
Copy link
Contributor

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.

Suggested change
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}

static int value = n; // may not be called in a constant expression
return value;
}
constexpr int prev(int x)
{ return --x; } // OK
constexpr int g(int x, int n) { // OK
int r = 1;
while (--n > 0) r *= x;
return r;
constexpr int uninit() { // \tcode{uninit} is constexpr-usable, but a program which calls
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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

struct { int a; } s; // \tcode{uninit} in a constant expression is ill-formed
return s.a;
Comment on lines +892 to +894
Copy link
Contributor

@frederick-vs-ja frederick-vs-ja Oct 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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 Base {
constexpr Base() = default; // OK
};
struct Derived : virtual Base {
constexpr Derived() = default; // error: constructor cannot be constexpr in a
}; // class or struct with virtual base classes
Copy link
Member

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)

\end{codeblock}
\end{example}

Expand Down