From f61dcaba33b93493e9deaf8f6d260e710260c1f2 Mon Sep 17 00:00:00 2001 From: Daniel Hannon Date: Mon, 15 Jun 2026 23:46:48 +0100 Subject: [PATCH 1/2] P4101R1 Consteval-only Values for C++26 --- source/basic.tex | 25 --------- source/classes.tex | 4 +- source/expressions.tex | 119 ++++++++++++++++++++++------------------ source/meta.tex | 9 +-- source/preprocessor.tex | 2 +- source/utilities.tex | 4 -- 6 files changed, 72 insertions(+), 91 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index c1f58de60a..8576f9c6e5 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -5399,31 +5399,6 @@ layout-compatible enumerations\iref{dcl.enum}, or layout-compatible standard-layout class types\iref{class.mem}. -\pnum -A type is \defn{consteval-only} if it is -\begin{itemize} -\item \tcode{std::meta::info}, -\item \cv{}~\tcode{T}, where \tcode{T} is a consteval-only type, -\item a pointer or reference to a consteval-only type, -\item an array of consteval-only type, -\item a function type having a return type or any parameter type that is consteval-only, -\item a class type with any non-static data member having consteval-only type, or -\item a type ``pointer to member of class \tcode{C} of type \tcode{T}'', -where at least one of \tcode{C} or \tcode{T} is a consteval-only type. -\end{itemize} -Every object of consteval-only type shall be -\begin{itemize} -\item -the object associated with a constexpr variable or a subobject thereof, -\item -a template parameter object\iref{temp.param} or a subobject thereof, or -\item -an object whose lifetime begins and ends -during the evaluation of a core constant expression. -\end{itemize} -Every function of consteval-only type shall be -an immediate function\iref{expr.const.imm}. - \rSec2[basic.fundamental]{Fundamental types} \pnum diff --git a/source/classes.tex b/source/classes.tex index 6cd80b2796..bae6223a76 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -4121,9 +4121,7 @@ \indextext{function!virtual|)} \pnum -A class with an immediate virtual function that overrides -a non-immediate virtual function -shall have consteval-only type\iref{basic.types.general}. +A non-immediate virtual function shall not be overridden by an immediate virtual function. An immediate virtual function shall not be overridden by a non-immediate virtual function. diff --git a/source/expressions.tex b/source/expressions.tex index 72f77d87bb..d2818aba4f 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -8418,6 +8418,7 @@ A type has \defnadj{constexpr-unknown}{representation} if it \begin{itemize} \item is a union, +\item is \tcode{std::meta::type_info}, \item is a pointer or pointer-to-member type, \item is volatile-qualified, \item is a class type with a non-static data member of reference type, or @@ -8907,58 +8908,55 @@ \rSec2[expr.const.const]{Constant expressions} \pnum -A \defnadj{constant}{expression} is either +A \defnadj{consteval-only}{value} is either \begin{itemize} -\item -a glvalue core constant expression $E$ for which +\item a reflection value\iref{basic.fundamental} that is not the null reflection value or +\item a pointer or pointer-to-member that points to an immediate function or to or past the end + of an immediate object. +\end{itemize} + +\pnum +An object is an \defnadj{immediate}{object} if its complete object has \begin{itemize} -\item -$E$ refers to a non-immediate function, -\item -$E$ designates an object \tcode{o}, and -if the complete object of \tcode{o} is of consteval-only type then so is $E$, +\item a constituent value that is consteval-only or +\item a constituent reference that refers to an immediate object or immediate function. +\end{itemize} + +\pnum +Every immediate object shall be +\begin{itemize} +\item the object associate with a constexpr variable or a subobject thereof, +\item a template parameter object\iref{temp.param} or a subject thereof, or +\item an object whose lifetime begins and ends during the evaluation of a core constant expression. \begin{example} \begin{codeblock} -struct Base { }; -struct Derived : Base { std::meta::info r; }; +consteval int plus1(int x) { return x + 1; } +template struct C {}; -consteval const Base& fn(const Derived& derived) { return derived; } +auto a = plus1; // error: immediate object not associated with constexpr variable +constexpr auto b = plus1; // OK +auto c = C(); // OK -constexpr Derived obj{.r=^^::}; // OK -constexpr const Derived& d = obj; // OK -constexpr const Base& b = fn(obj); // error: not a constant expression because \tcode{Derived} - // is a consteval-only type but \tcode{Base} is not. +auto d = ^^int; // error: immediate object not associated with constexpr variable +auto e = C<^^char>(); // OK \end{codeblock} \end{example} +Each expression $E$ that odr-uses a variable that declares or referes to an immediate object +shall be in an immediate function context; a diagnostic is required only if either +\item the innermost declaration that contains $E$ or +\item the defining declaration of the variable is reachable from the other. \end{itemize} -or -\item -a prvalue core constant expression whose result object\iref{basic.lval} (if any) -satisfies the following constraints: -\begin{itemize} -\item -each constituent reference refers to an object or a non-immediate function, -\item -no constituent value of scalar type is an indeterminate or erroneous value\iref{basic.indet}, -\item -no constituent value of pointer type is a pointer to an immediate function or -an invalid pointer value\iref{basic.compound}, -\item -no constituent value of pointer-to-member type designates an immediate function, and -\item -unless the value is of consteval-only type, + +\pnum +A core constant expression is a \defnadj{constant}{expression} unless it is a prvalue whose result +object\iref{basic.lval} has a constituent value that is an invalid pointer value\iref{basic.compound} +or is indeterminate or erroneous\iref{basic.indet} + +\pnum +A constant expression is an \defnadj{immediate}{constant}{expression} if it is either \begin{itemize} -\item -no constituent value of pointer-to-member type points to -a direct member of a consteval-only class type, -\item -no constituent value of pointer type points to or past an object -whose complete object is of consteval-only type, and -\item -no constituent reference refers to an object -whose complete object is of consteval-only type. -\end{itemize} -\end{itemize} +\item a glvalue that refers to an immediate object or an immediate function, or +\item a pr value whose result object is an immediate object \end{itemize} \begin{note} A glvalue core constant expression @@ -9277,12 +9275,29 @@ nor a subexpression of an immediate invocation, and \begin{itemize} \item -it is an \grammarterm{id-expression} or \grammarterm{splice-expression} -that designates an immediate function, +it is an immediate constant expression or +\begin{example} +\begin{codeblock} +consteval std::meta::info refl() { return ^^int; } +template +constexpr void ex() { + auto x = F(); +} +auto p = &ex; // error: immediate function because F() + // is an immediate constant expression +\end{codeblock} +\end{example} \item it is an immediate invocation that is not a constant expression, or -\item -it is of consteval-only type\iref{basic.types.general}. +\begin{example} +\begin{codeblock} +consteval int id(int x) { return x; } +template +constexpr auto apply_to(int i) { return F(i); } +auto p = &apply_to; // error: immediate function because F(i) + // is not a constant expression +\end{codeblock} +\end{example} \end{itemize} \pnum @@ -9304,19 +9319,15 @@ in an immediate-escalating function. \pnum -An \defnadj{immediate}{function} is a function that is +An \defnadj{immediate}{function} is a function that is either \begin{itemize} \item -declared with the \keyword{consteval} specifier, -\item -an immediate-escalating function -whose type is consteval-only\iref{basic.types.general}, or +declared with the \keyword{consteval} specifier, or \item an immediate-escalating function \tcode{\placeholder{F}} -whose function body contains either +whose function body contains \begin{itemize} -\item an immediate-escalating expression or -\item a definition of a non-constexpr variable with consteval-only type +\item an immediate-escalating expression \end{itemize} whose innermost enclosing non-block scope is \tcode{\placeholder{F}}'s function parameter scope. diff --git a/source/meta.tex b/source/meta.tex index 09b71fa44e..08052036a3 100644 --- a/source/meta.tex +++ b/source/meta.tex @@ -3370,7 +3370,6 @@ \pnum Reflection functions throw exceptions of type \tcode{meta::exception} to signal an error. -\tcode{meta::exception} is a consteval-only type. \indexlibraryctor{exception}% \begin{itemdecl} @@ -5150,7 +5149,9 @@ \end{codeblock} \pnum -The type \tcode{access_context} is a structural, consteval-only, non-aggregate type. +The type \tcode{access_context} is a structural, non-aggregate type. +A value \tcode{ac} of type \tcode{access_context} is consteval-only if +either \tcode{ac.scope()} or \tcode{ac.designating_class()} is consteval-only. Two values \tcode{ac1} and \tcode{ac2} of type \tcode{access_context} are template-argument-equivalent\iref{temp.type} if \tcode{ac1.scope()} and \tcode{ac2.scope()} are template-argument-equivalent @@ -6417,8 +6418,8 @@ \pnum The classes \tcode{data_member_options} and \tcode{data_member_options::\exposid{name-type}} -are consteval-only types\iref{basic.types.general}, -and are not structural types\iref{temp.param}. +are not structural types\iref{temp.param}. +Values of both types are consteval-only values. \begin{itemdecl} template diff --git a/source/preprocessor.tex b/source/preprocessor.tex index 0bfb7f194f..cdb0f63f1a 100644 --- a/source/preprocessor.tex +++ b/source/preprocessor.tex @@ -2385,7 +2385,7 @@ \defnxname{cpp_char8_t} & \tcode{202207L} \\ \rowsep \defnxname{cpp_concepts} & \tcode{202002L} \\ \rowsep \defnxname{cpp_conditional_explicit} & \tcode{201806L} \\ \rowsep -\defnxname{cpp_consteval} & \tcode{202211L} \\ \rowsep +\defnxname{cpp_consteval} & \tcode{202606L} \\ \rowsep \defnxname{cpp_constexpr} & \tcode{202406L} \\ \rowsep \defnxname{cpp_constexpr_dynamic_alloc} & \tcode{201907L} \\ \rowsep \defnxname{cpp_constexpr_exceptions} & \tcode{202411L} \\ \rowsep diff --git a/source/utilities.tex b/source/utilities.tex index f3e66eb429..ef8ce768eb 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -16360,10 +16360,6 @@ \item \tcode{is_trivially_copyable_v} is \tcode{true}. \end{itemize} -\pnum -\mandates -Neither \tcode{To} nor \tcode{From} are consteval-only types\iref{basic.types.general}. - \pnum \constantwhen Neither \tcode{To} nor \tcode{From} From cbe39a46eaa7a2cb17dfa7d5c108db029f151f0f Mon Sep 17 00:00:00 2001 From: Daniel Hannon Date: Wed, 17 Jun 2026 20:59:11 +0100 Subject: [PATCH 2/2] fixup: re-add CWG3136 --- source/expressions.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/expressions.tex b/source/expressions.tex index d2818aba4f..c4e342a107 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -8956,7 +8956,7 @@ A constant expression is an \defnadj{immediate}{constant}{expression} if it is either \begin{itemize} \item a glvalue that refers to an immediate object or an immediate function, or -\item a pr value whose result object is an immediate object +\item a prvalue whose result object (if any) is an immediate object \end{itemize} \begin{note} A glvalue core constant expression