|
7239 | 7239 | machine\iref{intro.execution}, would evaluate one of the following:
|
7240 | 7240 | \begin{itemize}
|
7241 | 7241 | \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} |
7245 | 7251 |
|
7246 | 7252 | \item
|
7247 | 7253 | a control flow that passes through
|
|
7266 | 7272 |
|
7267 | 7273 | \item
|
7268 | 7274 | 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 |
7274 | 7276 |
|
7275 | 7277 | \item
|
7276 | 7278 | an expression that would exceed the implementation-defined
|
|
7314 | 7316 | for a union whose active member (if any) is mutable,
|
7315 | 7317 | unless the lifetime of the union object began within the evaluation of $E$;
|
7316 | 7318 |
|
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 |
| - |
7329 | 7319 | \item
|
7330 | 7320 | in a \grammarterm{lambda-expression},
|
7331 | 7321 | a reference to \keyword{this} or to a variable with
|
|
7417 | 7407 | a \grammarterm{throw-expression}\iref{expr.throw};
|
7418 | 7408 |
|
7419 | 7409 | \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 |
7421 | 7414 | that would throw an exception;
|
7422 | 7415 |
|
7423 | 7416 | \item
|
|
7499 | 7492 | the evaluation of the underlying constructor call
|
7500 | 7493 | disqualifies $E$ from being a core constant expression.
|
7501 | 7494 |
|
| 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 | + |
7502 | 7560 | \pnum
|
7503 | 7561 | An object \tcode{a} is said to have \defnadj{constant}{destruction} if:
|
7504 | 7562 | \begin{itemize}
|
|
7612 | 7670 | object with static storage duration that either is not a temporary object or is
|
7613 | 7671 | a temporary object whose value satisfies the above constraints, or if
|
7614 | 7672 | 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} |
7615 | 7678 | \begin{example}
|
7616 | 7679 | \begin{codeblock}
|
7617 | 7680 | consteval int f() { return 42; }
|
|
0 commit comments