Skip to content

Commit e220906

Browse files
jensmaurertkoeppe
authored andcommitted
P2686R5 constexpr structured bindings and references to constexpr variables
Editorial notes: * Merge the change to [temp.arg.nontype] with existing text.
1 parent 36271ad commit e220906

File tree

4 files changed

+309
-82
lines changed

4 files changed

+309
-82
lines changed

source/basic.tex

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -441,24 +441,59 @@
441441
A variable is named by an expression
442442
if the expression is an \grammarterm{id-expression} that denotes it.
443443
A variable \tcode{x} that is named by a
444-
potentially-evaluated expression $E$
445-
is \defnx{odr-used}{odr-use} by $E$ unless
444+
potentially-evaluated expression $N$
445+
that appears at a point $P$
446+
is \defnx{odr-used}{odr-use} by $N$ unless
446447
\begin{itemize}
447448
\item
448-
\tcode{x} is a reference that is
449-
usable in constant expressions\iref{expr.const}, or
449+
\tcode{x} is a reference
450+
that is usable in constant expressions at $P$\iref{expr.const} or
450451
\item
451-
\tcode{x} is a variable of non-reference type that is
452-
usable in constant expressions and has no mutable subobjects, and
453-
$E$ is an element of the set of potential results of an expression
454-
of non-volatile-qualified non-class type
455-
to which the lvalue-to-rvalue conversion\iref{conv.lval} is applied, or
452+
$N$ is an element of the set of potential results of an expression $E$, where
453+
\begin{itemize}
454+
\item
455+
$E$ is a discarded-value expression\iref{expr.context}
456+
to which the lvalue-to-rvalue conversion is not applied or
457+
\item
458+
\tcode{x} is a non-volatile object
459+
that is usable in constant expressions at $P$ and
460+
has no mutable subobjects and
461+
\begin{itemize}
462+
\item
463+
$E$ is a class member access expression\iref{expr.ref}
464+
naming a non-static data member of reference type and
465+
whose object expression has non-volatile-qualified type or
456466
\item
457-
\tcode{x} is a variable of non-reference type, and
458-
$E$ is an element of the set of potential results
459-
of a discarded-value expression\iref{expr.context}
460-
to which the lvalue-to-rvalue conversion is not applied.
467+
the lvalue-to-rvalue conversion\iref{conv.lval} is applied to $E$ and
468+
$E$ has non-volatile-qualified non-class type
461469
\end{itemize}
470+
\end{itemize}
471+
\end{itemize}
472+
\begin{example}
473+
\begin{codeblock}
474+
int f(int);
475+
int g(int&);
476+
struct A {
477+
int x;
478+
};
479+
struct B {
480+
int& r;
481+
};
482+
int h(bool cond) {
483+
constexpr A a = {1};
484+
constexpr const volatile A& r = a; // odr-uses \tcode{a}
485+
int _ = f(cond ? a.x : r.x); // does not odr-use \tcode{a} or \tcode{r}
486+
int x, y;
487+
constexpr B b1 = {x}, b2 = {y}; // odr-uses \tcode{x} and \tcode{y}
488+
int _ = g(cond ? b1.r : b2.r); // does not odr-use \tcode{b1} or \tcode{b2}
489+
int _ = ((cond ? x : y), 0); // does not odr-use \tcode{x} or \tcode{y}
490+
return [] {
491+
return b1.r; // error: \tcode{b1} is odr-used here because the object
492+
// referred to by \tcode{b1.r} is not constexpr-referenceable here
493+
}();
494+
}
495+
\end{codeblock}
496+
\end{example}
462497

463498
\pnum
464499
A structured binding is odr-used if it appears as a potentially-evaluated expression.
@@ -6926,7 +6961,7 @@
69266961
\pnum
69276962
\indextext{initialization!constant}%
69286963
\defnx{Constant initialization}{constant initialization} is performed
6929-
if a variable or temporary object with static or thread storage duration
6964+
if a variable with static or thread storage duration
69306965
is constant-initialized\iref{expr.const}.
69316966
\indextext{initialization!zero-initialization}%
69326967
If constant initialization is not performed, a variable with static

source/declarations.tex

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@
212212
a \defn{structured binding declaration}\iref{dcl.struct.bind}.
213213
Each \grammarterm{decl-specifier} in the \grammarterm{decl-specifier-seq}
214214
shall be
215+
\tcode{constexpr},
216+
\tcode{constinit},
215217
\tcode{static},
216218
\tcode{thread_local},
217219
\tcode{auto}\iref{dcl.spec.auto}, or
@@ -849,7 +851,8 @@
849851

850852
\pnum
851853
The \keyword{constexpr} specifier shall be applied only to
852-
the definition of a variable or variable template or
854+
the definition of a variable or variable template,
855+
a structured binding declaration, or
853856
the declaration of a function or function template.
854857
The \keyword{consteval} specifier shall be applied only to
855858
the declaration of a function or function template.
@@ -994,9 +997,7 @@
994997
Such an object
995998
shall have literal type and
996999
shall be initialized.
997-
In any \keyword{constexpr} variable declaration,
998-
the full-expression of the initialization
999-
shall be a constant expression\iref{expr.const}.
1000+
A \keyword{constexpr} variable shall be constant-initializable\iref{expr.const}.
10001001
A \keyword{constexpr} variable that is an object,
10011002
as well as any temporary to which a \keyword{constexpr} reference is bound,
10021003
shall have constant destruction.
@@ -1007,6 +1008,16 @@
10071008
};
10081009
constexpr pixel ur = { 1294, 1024 }; // OK
10091010
constexpr pixel origin; // error: initializer missing
1011+
1012+
namespace N {
1013+
void f() {
1014+
int x;
1015+
constexpr int& ar = x; // OK
1016+
static constexpr int& sr = x; // error: \tcode{x} is not constexpr-representable
1017+
// at the point indicated below
1018+
}
1019+
// immediate scope here is that of \tcode{N}
1020+
}
10101021
\end{codeblock}
10111022
\end{example}
10121023

@@ -1015,7 +1026,12 @@
10151026

10161027
\pnum
10171028
The \keyword{constinit} specifier shall be applied only
1018-
to a declaration of a variable with static or thread storage duration.
1029+
to a declaration of a variable with static or thread storage duration
1030+
or to a structured binding declaration\iref{dcl.struct.bind}.
1031+
\begin{note}
1032+
A structured binding declaration introduces a uniquely named variable,
1033+
to which the \tcode{constinit} specifier applies.
1034+
\end{note}
10191035
If the specifier is applied to any declaration of a variable,
10201036
it shall be applied to the initializing declaration.
10211037
No diagnostic is required if no \keyword{constinit} declaration
@@ -7033,8 +7049,10 @@
70337049
appertains to the structured binding so introduced.
70347050
Let \cv{} denote the \grammarterm{cv-qualifier}{s} in
70357051
the \grammarterm{decl-specifier-seq} and
7036-
\placeholder{S} consist of the \grammarterm{storage-class-specifier}{s} of
7037-
the \grammarterm{decl-specifier-seq} (if any).
7052+
\placeholder{S} consist of
7053+
each \grammarterm{decl-specifier} of the \grammarterm{decl-specifier-seq}
7054+
that is \tcode{constexpr}, \tcode{constinit}, or
7055+
a \grammarterm{storage-class-specifier}.
70387056
A \cv{} that includes \tcode{volatile} is deprecated;
70397057
see~\ref{depr.volatile.type}.
70407058
First, a variable with a unique name \exposid{e} is introduced. If the

0 commit comments

Comments
 (0)