Skip to content

[CWG Motion 6 2024-06] P2963R3 Ordering of constraints involving fold expressions #7113

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
Jul 12, 2024
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
26 changes: 26 additions & 0 deletions source/compatibility.tex
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,32 @@
\end{codeblock}
\end{example}

\rSec2[diff.cpp23.temp]{\ref{temp}: templates}

\diffref{temp.constr}
\change
Some atomic constraints become fold expanded constraints.
\rationale
Permit the subsumption of fold expressions.
\effect
Valid \CppXXIII{} code may become ill-formed.
\begin{example}
\begin{codeblock}
template <typename ...V> struct A;
struct S {
static constexpr int compare(const S&) { return 1; }
};

template <typename ...T, typename ...U>
void f(A<T ...> *, A<U ...> *)
requires (T::compare(U{}) && ...); // was well-formed (atomic constraint of type \tcode{bool}),
// now ill-formed (results in an atomic constraint of type \tcode{int})
void g(A<S, S> *ap) {
f(ap, ap);
}
\end{codeblock}
\end{example}

\rSec2[diff.cpp23.library]{\ref{library}: library introduction}

\diffref{headers}
Expand Down
98 changes: 93 additions & 5 deletions source/templates.tex
Original file line number Diff line number Diff line change
Expand Up @@ -1480,11 +1480,12 @@
A \defn{constraint} is a sequence of logical operations and
operands that specifies requirements on template arguments.
The operands of a logical operation are constraints.
There are three different kinds of constraints:
There are four different kinds of constraints:
\begin{itemize}
\item conjunctions\iref{temp.constr.op},
\item disjunctions\iref{temp.constr.op}, and
\item atomic constraints\iref{temp.constr.atomic}.
\item disjunctions\iref{temp.constr.op},
\item atomic constraints\iref{temp.constr.atomic}, and
\item fold expanded constraints\iref{temp.constr.fold}.
\end{itemize}

\pnum
Expand Down Expand Up @@ -1719,6 +1720,47 @@
\end{codeblock}
\end{example}

\rSec3[temp.constr.fold]{Fold expanded constraint}

\pnum
A \defnadj{fold expanded}{constraint} is formed from a constraint $C$ and
a \grammarterm{fold-operator}
which can either be \tcode{\&\&} or \tcode{||}.
A fold expanded constraint is a pack expansion\iref{temp.variadic}.
Let $N$ be the number of elements
in the pack expansion parameters\iref{temp.variadic}.

\pnum
A fold expanded constraint whose \grammarterm{fold-operator} is \tcode{\&\&}
is satisfied if it is a valid pack expansion and
if $N = 0$ or if for each $i$ where $0 \le i < N$ in increasing order,
$C$ is satisfied
when replacing each pack expansion parameter
with the corresponding $i^\text{th}$ element.
No substitution takes place for any $i$ greater than
the smallest $i$ for which the constraint is not satisfied.

\pnum
A fold expanded constraint whose \grammarterm{fold-operator} is \tcode{||}
is satisfied if it is a valid pack expansion,
$N > 0$, and if for $i$ where $0 \le i < N$ in increasing order,
there is a smallest $i$ for which $C$ is satisfied
when replacing each pack expansion parameter
with the corresponding $i^\text{th}$ element.
No substitution takes place for any $i$ greater than
the smallest $i$ for which the constraint is satisfied.

\pnum
\begin{note}
If the pack expansion expands packs of different size,
then it is invalid and the fold expanded constraint is not satisfied.
\end{note}

\pnum
Two fold expanded constraints are \defnadj{compatible for}{subsumption}
if their respective constraints both contain
an equivalent unexpanded pack\iref{temp.over.link}.

\rSec2[temp.constr.decl]{Constrained declarations}

\pnum
Expand Down Expand Up @@ -1894,6 +1936,40 @@
in the parameter mapping.
\end{example}

\item
For a \grammarterm{fold-operator}\iref{expr.prim.fold}
that is either \tcode{\&\&} or \tcode{||},
the normal form of an expression
\tcode{( ... \grammarterm{fold-operator} E )} is the normal form of
\tcode{( E \grammarterm{fold-operator} ... )}.

\item
For a \grammarterm{fold-operator}
that is either \tcode{\&\&} or \tcode{||},
the normal form of an expression
\tcode{( E1 \grammarterm{fold-operator} ... \grammarterm{fold-operator} E2 )}
is the the normal form of
\begin{itemize}
\item
\tcode{( E1 \grammarterm{fold-operator} ... ) \grammarterm{fold-operator} E2}
if \tcode{E1} contains an unexpanded pack, or
\item
\tcode{E1 \grammarterm{fold-operator} ( E2 \grammarterm{fold-operator} ... )}
otherwise.
\end{itemize}

\item
The normal form of \tcode{( E \&\& ... )} is
a fold expanded constraint\iref{temp.constr.fold}
whose constraint is the normal form of \tcode{E} and
whose \grammarterm{fold-operator} is \tcode{\&\&}.

\item
The normal form of \tcode{( E || ... )} is
a fold expanded constraint
whose constraint is the normal form of \tcode{E} and
whose \grammarterm{fold-operator} is \tcode{||}.

\item
The normal form of any other expression \tcode{E} is
the atomic constraint
Expand Down Expand Up @@ -1971,11 +2047,17 @@
\item
a disjunctive clause $P_i$ subsumes a conjunctive clause $Q_j$ if and only
if there exists an atomic constraint $P_{ia}$ in $P_i$ for which there exists
an atomic constraint $Q_{jb}$ in $Q_j$ such that $P_{ia}$ subsumes $Q_{jb}$, and
an atomic constraint $Q_{jb}$ in $Q_j$ such that $P_{ia}$ subsumes $Q_{jb}$,

\item an atomic constraint $A$ subsumes another atomic constraint
$B$ if and only if $A$ and $B$ are identical using the
rules described in \ref{temp.constr.atomic}.
rules described in \ref{temp.constr.atomic}, and

\item a fold expanded constraint $A$ subsumes
another fold expanded constraint $B$
if they are compatible for subsumption,
have the same \grammarterm{fold-operator}, and
the constraint of $A$ subsumes that of $B$.
\end{itemize}
%
\begin{example}
Expand Down Expand Up @@ -2789,6 +2871,9 @@
\item In a \grammarterm{fold-expression}\iref{expr.prim.fold};
the pattern is the \grammarterm{cast-expression}
that contains an unexpanded pack.

\item In a fold expanded constraint\iref{temp.constr.fold};
the pattern is the constraint of that fold expanded constraint.
\end{itemize}

\begin{example}
Expand Down Expand Up @@ -2976,6 +3061,9 @@
\tcode{,} & \tcode{void()} \\
\end{floattable}

\pnum
A fold expanded constraint is not instantiated\iref{temp.constr.fold}.

\pnum
The instantiation of any other pack expansion
produces a list of elements $\tcode{E}_1, \tcode{E}_2, \dotsc, \tcode{E}_N$.
Expand Down
Loading