Skip to content

P2448R2 Relaxing some constexpr restrictions #5656

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

Merged
merged 1 commit into from
Aug 5, 2022
Merged
Show file tree
Hide file tree
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
57 changes: 4 additions & 53 deletions source/classes.tex
Original file line number Diff line number Diff line change
Expand Up @@ -1092,13 +1092,6 @@
and, if the class is not abstract\iref{class.abstract}, its virtual base
classes are called its \term{potentially constructed subobjects}.

\pnum
A defaulted special member function is
\indextext{member function!constexpr-compatible}%
\defnx{constexpr-compatible}{constexpr-compatible!defaulted special member function}
if the corresponding implicitly-declared special member function
would be a constexpr function.

\rSec2[class.ctor]{Constructors}%

\rSec3[class.ctor.general]{General}%
Expand Down Expand Up @@ -1314,7 +1307,7 @@
If that user-written default constructor would be ill-formed,
the program is ill-formed.
If that user-written default constructor would satisfy the requirements
of a constexpr constructor\iref{dcl.constexpr}, the implicitly-defined
of a constexpr function\iref{dcl.constexpr}, the implicitly-defined
default constructor is \keyword{constexpr}.
Before the defaulted default constructor for a class is
implicitly defined,
Expand Down Expand Up @@ -1611,7 +1604,7 @@
its odr-use\iref{term.odr.use,class.temporary}.
\end{note}
If the implicitly-defined constructor would satisfy the requirements of a
constexpr constructor\iref{dcl.constexpr}, the implicitly-defined
constexpr function\iref{dcl.constexpr}, the implicitly-defined
constructor is \keyword{constexpr}.

\pnum
Expand Down Expand Up @@ -1911,20 +1904,7 @@
to assign to an object of its class type),
when it is needed for constant evaluation\iref{expr.const}, or
when it is explicitly defaulted after its first declaration.
The implicitly-defined copy/move assignment operator is \keyword{constexpr} if
\begin{itemize}
\item
\tcode{X} is a literal type, and

\item
the assignment operator selected to copy/move each direct base class subobject
is a constexpr function, and

\item
for each non-static data member of \tcode{X} that is of class type (or array
thereof), the assignment operator selected to copy/move that member is a
constexpr function.
\end{itemize}
The implicitly-defined copy/move assignment operator is \keyword{constexpr}.

\pnum
Before the defaulted copy/move assignment operator for a class is
Expand Down Expand Up @@ -2132,7 +2112,7 @@

\pnum
A defaulted destructor is a constexpr destructor
if it satisfies the requirements for a constexpr destructor\iref{dcl.constexpr}.
if it satisfies the requirements for a constexpr function\iref{dcl.constexpr}.

\pnum
A destructor
Expand Down Expand Up @@ -6503,35 +6483,6 @@
\tcode{a @ b} is a valid expression.
\end{itemize}

\pnum
A defaulted comparison function is
\indextext{operator!comparison!constexpr-compatible}%
\defnx{constexpr-compatible}{constexpr-compatible!defaulted comparison operator}
if it
satisfies the requirements for a constexpr function\iref{dcl.constexpr} and
no overload resolution
performed when determining whether to delete the function
results in a usable candidate that is a non-constexpr function.
\begin{note}
This includes the overload resolutions performed:

\begin{itemize}
\item
for an \tcode{operator<=>} whose return type is not \keyword{auto},
when determining whether a synthesized three-way comparison is defined,

\item
for an \tcode{operator<=>} whose return type is \keyword{auto} or
for an \tcode{operator==},
for a comparison between an element of the expanded list of
subobjects and itself, or

\item
for a secondary comparison operator \tcode{@},
for the expression \tcode{x @ y}.
\end{itemize}
\end{note}

\pnum
If the \grammarterm{member-specification}
does not explicitly declare
Expand Down
94 changes: 7 additions & 87 deletions source/declarations.tex
Original file line number Diff line number Diff line change
Expand Up @@ -770,12 +770,6 @@
The definition of a constexpr function shall satisfy the following
requirements:
\begin{itemize}
\item
its return type (if any) shall be a literal type;

\item
each of its parameter types shall be a literal type;

\item
it shall not be a coroutine\iref{dcl.fct.def.coroutine};

Expand Down Expand Up @@ -816,78 +810,6 @@
\end{codeblock}
\end{example}

\pnum
\indextext{specifier!\idxcode{constexpr}!constructor}%
The definition of a constexpr constructor
whose \grammarterm{function-body} is not \tcode{= delete}
shall additionally satisfy the following requirements:
\begin{itemize}

\item
for a non-delegating constructor, every constructor selected to initialize non-static
data members and base class subobjects shall be a constexpr constructor;

\item
for a delegating constructor, the target constructor shall be a constexpr
constructor.
\end{itemize}

\begin{example}
\begin{codeblock}
struct Length {
constexpr explicit Length(int i = 0) : val(i) { }
private:
int val;
};
\end{codeblock}
\end{example}

\pnum
The definition of a constexpr destructor
whose \grammarterm{function-body} is not \tcode{= delete}
shall additionally satisfy the following requirement:
\begin{itemize}
\item
for every subobject of class type or
(possibly multi-dimensional) array thereof,
that class type shall have a constexpr destructor.
\end{itemize}

\pnum
For a constexpr function or constexpr constructor
that is neither defaulted nor a template,
if no argument values exist such that
an invocation of the function or constructor could be an evaluated subexpression of a core
constant expression\iref{expr.const}, or,
for a constructor, an evaluated subexpression of
the initialization full-expression of some constant-initialized object\iref{basic.start.static},
the program is ill-formed, no diagnostic required.
\begin{example}
\begin{codeblock}
constexpr int f(bool b)
{ return b ? throw 0 : 0; } // OK
constexpr int f() { return f(true); } // ill-formed, no diagnostic required

struct B {
constexpr B(int x) : i(0) { } // \tcode{x} is unused
int i;
};

int global;

struct D : B {
constexpr D() : B(global) { } // ill-formed, no diagnostic required
// lvalue-to-rvalue conversion on non-constant \tcode{global}
};

constexpr int f(int x) {
static int n = x;
return n + x; // ill-formed, no diagnostic required
// all calls reach the static variable declaration
}
\end{codeblock}
\end{example}

\pnum
If the instantiated template specialization of a constexpr function
template
Expand All @@ -896,10 +818,7 @@
function,
that specialization is still a constexpr function,
even though a call to such a function cannot appear in a constant
expression. If no specialization of the template would satisfy the
requirements for a constexpr function
when considered as a non-template function, the template is
ill-formed, no diagnostic required.
expression.

\pnum
An invocation of a constexpr function in a given context
Expand All @@ -919,6 +838,10 @@
This can indirectly cause calls to \tcode{std::is_constant_evaluated}
within an invocation of the function to produce a different value.
\end{note}
\begin{note}
It is possible to write a constexpr function for which
no invocation satisfies the requirements of a core constant expression.
\end{note}

\pnum
The \keyword{constexpr} and \keyword{consteval} specifiers have no
Expand Down Expand Up @@ -6249,18 +6172,15 @@
\end{itemize}

\pnum
An explicitly-defaulted function that is not defined as deleted may be declared
\keyword{constexpr} or \keyword{consteval} only
if it is constexpr-compatible\iref{special,class.compare.default}.
A function explicitly defaulted on its first declaration
is implicitly inline\iref{dcl.inline},
and is implicitly constexpr\iref{dcl.constexpr} if it is constexpr-compatible.
and is implicitly constexpr\iref{dcl.constexpr}
if it satisfies the requirements for a constexpr function.

\pnum
\begin{example}
\begin{codeblock}
struct S {
constexpr S() = default; // error: implicit \tcode{S()} is not \keyword{constexpr}
S(int a = 0) = default; // error: default argument
void operator=(const S&) = default; // error: non-matching return type
~S() noexcept(false) = default; // OK, despite mismatched exception specification
Expand Down
2 changes: 1 addition & 1 deletion source/preprocessor.tex
Original file line number Diff line number Diff line change
Expand Up @@ -1760,7 +1760,7 @@
\defnxname{cpp_char8_t} & \tcode{201811L} \\ \rowsep
\defnxname{cpp_concepts} & \tcode{202002L} \\ \rowsep
\defnxname{cpp_conditional_explicit} & \tcode{201806L} \\ \rowsep
\defnxname{cpp_constexpr} & \tcode{202110L} \\ \rowsep
\defnxname{cpp_constexpr} & \tcode{202207L} \\ \rowsep
\defnxname{cpp_constexpr_dynamic_alloc} & \tcode{201907L} \\ \rowsep
\defnxname{cpp_constexpr_in_decltype} & \tcode{201711L} \\ \rowsep
\defnxname{cpp_consteval} & \tcode{201811L} \\ \rowsep
Expand Down