Skip to content

Commit 3660eb1

Browse files
jensmaurertkoeppe
authored andcommitted
P2280R4 Using unknown pointers and references in constant expressions
1 parent b834e4e commit 3660eb1

File tree

1 file changed

+84
-21
lines changed

1 file changed

+84
-21
lines changed

source/expressions.tex

Lines changed: 84 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7239,9 +7239,15 @@
72397239
machine\iref{intro.execution}, would evaluate one of the following:
72407240
\begin{itemize}
72417241
\item
7242-
\keyword{this}\iref{expr.prim.this}, except in a constexpr
7243-
function\iref{dcl.constexpr} that is being evaluated as part
7244-
of $E$;
7242+
\keyword{this}\iref{expr.prim.this}, except
7243+
\begin{itemize}
7244+
\item
7245+
in a constexpr function\iref{dcl.constexpr}
7246+
that is being evaluated as part of $E$ or
7247+
\item
7248+
when appearing as the \grammarterm{postfix-expression} of
7249+
an implicit or explicit class member access expression\iref{expr.ref};
7250+
\end{itemize}
72457251

72467252
\item
72477253
a control flow that passes through
@@ -7266,11 +7272,7 @@
72667272

72677273
\item
72687274
an invocation of a virtual function\iref{class.virtual}
7269-
for an object unless
7270-
\begin{itemize}
7271-
\item the object is usable in constant expressions or
7272-
\item its lifetime began within the evaluation of $E$;
7273-
\end{itemize}
7275+
for an object whose dynamic type is constexpr-unknown
72747276

72757277
\item
72767278
an expression that would exceed the implementation-defined
@@ -7314,18 +7316,6 @@
73147316
for a union whose active member (if any) is mutable,
73157317
unless the lifetime of the union object began within the evaluation of $E$;
73167318

7317-
\item
7318-
an \grammarterm{id-expression} that refers to a variable or
7319-
data member of reference type
7320-
unless the reference has a preceding initialization and either
7321-
\begin{itemize}
7322-
\item
7323-
it is usable in constant expressions or
7324-
7325-
\item
7326-
its lifetime began within the evaluation of $E$;
7327-
\end{itemize}
7328-
73297319
\item
73307320
in a \grammarterm{lambda-expression},
73317321
a reference to \keyword{this} or to a variable with
@@ -7417,7 +7407,10 @@
74177407
a \grammarterm{throw-expression}\iref{expr.throw};
74187408

74197409
\item
7420-
a \keyword{dynamic_cast}\iref{expr.dynamic.cast} or \keyword{typeid}\iref{expr.typeid} expression
7410+
a \keyword{dynamic_cast}\iref{expr.dynamic.cast} or
7411+
\keyword{typeid}\iref{expr.typeid} expression
7412+
on a glvalue that refers to an object
7413+
whose dynamic type is constexpr-unknown or
74217414
that would throw an exception;
74227415

74237416
\item
@@ -7499,6 +7492,71 @@
74997492
the evaluation of the underlying constructor call
75007493
disqualifies $E$ from being a core constant expression.
75017494

7495+
\pnum
7496+
During the evaluation of an expression $E$ as a core constant expression,
7497+
all \grammarterm{id-expression}s and uses of \tcode{*\keyword{this}}
7498+
that refer to an object or reference
7499+
whose lifetime did not begin with the evaluation of $E$
7500+
are treated as referring to a specific instance of that object or reference
7501+
whose lifetime and that of all subobjects (including all union members)
7502+
includes the entire constant evaluation.
7503+
For such an object that is not usable in constant expressions,
7504+
the dynamic type of the object is \defn{constexpr-unknown}.
7505+
For such a reference that is not usable in constant expressions,
7506+
the reference is treated as binding to
7507+
an unspecified object of the referenced type
7508+
whose lifetime and that of all subobjects includes
7509+
the entire constant evaluation and whose dynamic type is constexpr-unknown.
7510+
\begin{example}
7511+
\begin{codeblock}
7512+
template <typename T, size_t N>
7513+
constexpr size_t array_size(T (&)[N]) {
7514+
return N;
7515+
}
7516+
7517+
void use_array(int const (&gold_medal_mel)[2]) {
7518+
constexpr auto gold = array_size(gold_medal_mel); // OK
7519+
}
7520+
7521+
constexpr auto olympic_mile() {
7522+
const int ledecky = 1500;
7523+
return []{ return ledecky; };
7524+
}
7525+
static_assert(olympic_mile()() == 1500); // OK
7526+
7527+
struct Swim {
7528+
constexpr int phelps() { return 28; }
7529+
virtual constexpr int lochte() { return 12; }
7530+
int coughlin = 12;
7531+
};
7532+
7533+
constexpr int how_many(Swim& swam) {
7534+
Swim* p = &swam;
7535+
return (p + 1 - 1)->phelps();
7536+
}
7537+
7538+
void splash(Swim& swam) {
7539+
static_assert(swam.phelps() == 28); // OK
7540+
static_assert((&swam)->phelps() == 28); // OK
7541+
Swim* pswam = &swam;
7542+
static_assert(pswam->phelps() == 28); // error: lvalue-to-rvalue conversion on a pointer
7543+
// not usable in constant expressions
7544+
static_assert(how_many(swam) == 28); // OK
7545+
static_assert(Swim().lochte() == 12); // OK
7546+
static_assert(swam.lochte() == 12); // error: invoking virtual function on reference
7547+
// with constexpr-unknown dynamic type
7548+
static_assert(swam.coughlin == 12); // error: lvalue-to-rvalue conversion on an object
7549+
// not usable in constant expressions
7550+
}
7551+
7552+
extern Swim dc;
7553+
extern Swim& trident;
7554+
7555+
constexpr auto& sandeno = typeid(dc); // OK, can only be \tcode{typeid(Swim)}
7556+
constexpr auto& gallagher = typeid(trident); // error: constexpr-unknown dynamic type
7557+
\end{codeblock}
7558+
\end{example}
7559+
75027560
\pnum
75037561
An object \tcode{a} is said to have \defnadj{constant}{destruction} if:
75047562
\begin{itemize}
@@ -7612,6 +7670,11 @@
76127670
object with static storage duration that either is not a temporary object or is
76137671
a temporary object whose value satisfies the above constraints, or if
76147672
it is a non-immediate function.
7673+
\begin{note}
7674+
A glvalue core constant expression
7675+
that either refers to or points to an unspecified object
7676+
is not a constant expression.
7677+
\end{note}
76157678
\begin{example}
76167679
\begin{codeblock}
76177680
consteval int f() { return 42; }

0 commit comments

Comments
 (0)