|
7289 | 7289 | machine\iref{intro.execution}, would evaluate one of the following:
|
7290 | 7290 | \begin{itemize}
|
7291 | 7291 | \item
|
7292 |
| -\keyword{this}\iref{expr.prim.this}, except in a constexpr |
7293 |
| -function\iref{dcl.constexpr} that is being evaluated as part |
7294 |
| -of $E$; |
| 7292 | +\keyword{this}\iref{expr.prim.this}, except |
| 7293 | +\begin{itemize} |
| 7294 | +\item |
| 7295 | +in a constexpr function\iref{dcl.constexpr} |
| 7296 | +that is being evaluated as part of $E$ or |
| 7297 | +\item |
| 7298 | +when appearing as the \grammarterm{postfix-expression} of |
| 7299 | +an implicit or explicit class member access expression\iref{expr.ref}; |
| 7300 | +\end{itemize} |
7295 | 7301 |
|
7296 | 7302 | \item
|
7297 | 7303 | a control flow that passes through
|
|
7316 | 7322 |
|
7317 | 7323 | \item
|
7318 | 7324 | an invocation of a virtual function\iref{class.virtual}
|
7319 |
| -for an object unless |
7320 |
| - \begin{itemize} |
7321 |
| - \item the object is usable in constant expressions or |
7322 |
| - \item its lifetime began within the evaluation of $E$; |
7323 |
| - \end{itemize} |
| 7325 | +for an object whose dynamic type is constexpr-unknown; |
7324 | 7326 |
|
7325 | 7327 | \item
|
7326 | 7328 | an expression that would exceed the implementation-defined
|
|
7364 | 7366 | for a union whose active member (if any) is mutable,
|
7365 | 7367 | unless the lifetime of the union object began within the evaluation of $E$;
|
7366 | 7368 |
|
7367 |
| -\item |
7368 |
| -an \grammarterm{id-expression} that refers to a variable or |
7369 |
| -data member of reference type |
7370 |
| -unless the reference has a preceding initialization and either |
7371 |
| -\begin{itemize} |
7372 |
| - \item |
7373 |
| - it is usable in constant expressions or |
7374 |
| - |
7375 |
| - \item |
7376 |
| - its lifetime began within the evaluation of $E$; |
7377 |
| -\end{itemize} |
7378 |
| - |
7379 | 7369 | \item
|
7380 | 7370 | in a \grammarterm{lambda-expression},
|
7381 | 7371 | a reference to \keyword{this} or to a variable with
|
|
7467 | 7457 | a \grammarterm{throw-expression}\iref{expr.throw};
|
7468 | 7458 |
|
7469 | 7459 | \item
|
7470 |
| -a \keyword{dynamic_cast}\iref{expr.dynamic.cast} or \keyword{typeid}\iref{expr.typeid} expression |
| 7460 | +a \keyword{dynamic_cast}\iref{expr.dynamic.cast} or |
| 7461 | +\keyword{typeid}\iref{expr.typeid} expression |
| 7462 | +on a glvalue that refers to an object |
| 7463 | +whose dynamic type is constexpr-unknown or |
7471 | 7464 | that would throw an exception;
|
7472 | 7465 |
|
7473 | 7466 | \item
|
|
7549 | 7542 | the evaluation of the underlying constructor call
|
7550 | 7543 | disqualifies $E$ from being a core constant expression.
|
7551 | 7544 |
|
| 7545 | +\pnum |
| 7546 | +During the evaluation of an expression $E$ as a core constant expression, |
| 7547 | +all \grammarterm{id-expression}s and uses of \tcode{*\keyword{this}} |
| 7548 | +that refer to an object or reference |
| 7549 | +whose lifetime did not begin with the evaluation of $E$ |
| 7550 | +are treated as referring to a specific instance of that object or reference |
| 7551 | +whose lifetime and that of all subobjects (including all union members) |
| 7552 | +includes the entire constant evaluation. |
| 7553 | +For such an object that is not usable in constant expressions, |
| 7554 | +the dynamic type of the object is \defn{constexpr-unknown}. |
| 7555 | +For such a reference that is not usable in constant expressions, |
| 7556 | +the reference is treated as binding to |
| 7557 | +an unspecified object of the referenced type |
| 7558 | +whose lifetime and that of all subobjects includes |
| 7559 | +the entire constant evaluation and whose dynamic type is constexpr-unknown. |
| 7560 | +\begin{example} |
| 7561 | +\begin{codeblock} |
| 7562 | +template <typename T, size_t N> |
| 7563 | +constexpr size_t array_size(T (&)[N]) { |
| 7564 | + return N; |
| 7565 | +} |
| 7566 | + |
| 7567 | +void use_array(int const (&gold_medal_mel)[2]) { |
| 7568 | + constexpr auto gold = array_size(gold_medal_mel); // OK |
| 7569 | +} |
| 7570 | + |
| 7571 | +constexpr auto olympic_mile() { |
| 7572 | + const int ledecky = 1500; |
| 7573 | + return []{ return ledecky; }; |
| 7574 | +} |
| 7575 | +static_assert(olympic_mile()() == 1500); // OK |
| 7576 | + |
| 7577 | +struct Swim { |
| 7578 | + constexpr int phelps() { return 28; } |
| 7579 | + virtual constexpr int lochte() { return 12; } |
| 7580 | + int coughlin = 12; |
| 7581 | +}; |
| 7582 | + |
| 7583 | +constexpr int how_many(Swim& swam) { |
| 7584 | + Swim* p = &swam; |
| 7585 | + return (p + 1 - 1)->phelps(); |
| 7586 | +} |
| 7587 | + |
| 7588 | +void splash(Swim& swam) { |
| 7589 | + static_assert(swam.phelps() == 28); // OK |
| 7590 | + static_assert((&swam)->phelps() == 28); // OK |
| 7591 | + Swim* pswam = &swam; |
| 7592 | + static_assert(pswam->phelps() == 28); // error: lvalue-to-rvalue conversion on a pointer |
| 7593 | + // not usable in constant expressions |
| 7594 | + static_assert(how_many(swam) == 28); // OK |
| 7595 | + static_assert(Swim().lochte() == 12); // OK |
| 7596 | + static_assert(swam.lochte() == 12); // error: invoking virtual function on reference |
| 7597 | + // with constexpr-unknown dynamic type |
| 7598 | + static_assert(swam.coughlin == 12); // error: lvalue-to-rvalue conversion on an object |
| 7599 | + // not usable in constant expressions |
| 7600 | +} |
| 7601 | + |
| 7602 | +extern Swim dc; |
| 7603 | +extern Swim& trident; |
| 7604 | + |
| 7605 | +constexpr auto& sandeno = typeid(dc); // OK, can only be \tcode{typeid(Swim)} |
| 7606 | +constexpr auto& gallagher = typeid(trident); // error: constexpr-unknown dynamic type |
| 7607 | +\end{codeblock} |
| 7608 | +\end{example} |
| 7609 | + |
7552 | 7610 | \pnum
|
7553 | 7611 | An object \tcode{a} is said to have \defnadj{constant}{destruction} if:
|
7554 | 7612 | \begin{itemize}
|
|
7662 | 7720 | object with static storage duration that either is not a temporary object or is
|
7663 | 7721 | a temporary object whose value satisfies the above constraints, or if
|
7664 | 7722 | it is a non-immediate function.
|
| 7723 | +\begin{note} |
| 7724 | +A glvalue core constant expression |
| 7725 | +that either refers to or points to an unspecified object |
| 7726 | +is not a constant expression. |
| 7727 | +\end{note} |
7665 | 7728 | \begin{example}
|
7666 | 7729 | \begin{codeblock}
|
7667 | 7730 | consteval int f() { return 42; }
|
|
0 commit comments