From 09943137733b766a750dee69b96acb4c3949afad Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 14 Nov 2018 13:14:43 +0100 Subject: [PATCH] P1073R3 Immediate functions --- source/basic.tex | 2 ++ source/classes.tex | 12 ++++++- source/compatibility.tex | 27 +++++++++++---- source/declarations.tex | 64 ++++++++++++++++++++-------------- source/expressions.tex | 75 +++++++++++++++++++++++++++++++++++----- source/lex.tex | 9 ++--- source/macros.tex | 6 ++-- source/templates.tex | 2 +- 8 files changed, 149 insertions(+), 48 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index ce17b59965..21b1980d30 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -4845,6 +4845,8 @@ \item a \grammarterm{constant-expression}\iref{expr.const}, \item +an immediate invocation\iref{expr.const}, +\item an \grammarterm{init-declarator}\iref{dcl.decl} or a \grammarterm{mem-initializer}\iref{class.base.init}, including the constituent expressions of the initializer, diff --git a/source/classes.tex b/source/classes.tex index bba2e8d807..10ac4e2630 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -3709,7 +3709,11 @@ \begin{note} Virtual functions support dynamic binding and object-oriented programming. \end{note} A class that declares or inherits a virtual function is -called a \defnadj{polymorphic}{class}. +called a \defnadj{polymorphic}{class}.\footnote{If +all virtual functions are immediate functions, +the class is still polymorphic even though +its internal representation might not otherwise require +any additions for that polymorphic behavior.} \pnum If a virtual member function \tcode{vf} is declared in a class @@ -4041,6 +4045,12 @@ function with a deleted definition.% \indextext{function!virtual|)} +\pnum +A \tcode{consteval} virtual function shall not override +a virtual function that is not \tcode{consteval}. +A \tcode{consteval} virtual function shall not be overridden by +a virtual function that is not \tcode{consteval}. + \pnum If an overriding function specifies contract conditions\iref{dcl.attr.contract}, it shall specify the same list of contract conditions as diff --git a/source/compatibility.tex b/source/compatibility.tex index 89e29541ac..9d2ea7073f 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -1795,15 +1795,28 @@ \diffref{lex.key} \change New keywords. \rationale Required for new features. -The \tcode{requires} keyword is added -to introduce constraints through a \grammarterm{requires-clause} or -a \grammarterm{requires-expression}. The \tcode{concept} keyword is -added to enable the definition of concepts\iref{temp.concept}. +\begin{itemize} +\item The \tcode{char8_t} keyword is added to differentiate the types of ordinary and UTF-8 literals\iref{lex.string}. -\effect -Valid ISO \CppXVII{} code using \tcode{concept}, \tcode{requires}, -or \tcode{char8_t} as an identifier is not valid in this International Standard. +\item +The \tcode{concept} keyword is +added to enable the definition of concepts\iref{temp.concept}. +\item +The \tcode{consteval} keyword is added to +declare immediate functions\iref{dcl.constexpr}. +\item +The \tcode{requires} keyword is added +to introduce constraints through a \grammarterm{requires-clause} or +a \grammarterm{requires-expression}. +\end{itemize} +\effectafteritemize +Valid ISO \CppXVII{} code using +\tcode{char8_t}, +\tcode{concept}, +\tcode{consteval}, +or \tcode{requires} +as an identifier is not valid in this International Standard. \diffref{lex.operators} \change New operator \tcode{<=>}. diff --git a/source/declarations.tex b/source/declarations.tex index db307461b6..7f1670a8b1 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -253,6 +253,7 @@ \terminal{friend}\br \terminal{typedef}\br \terminal{constexpr}\br + \terminal{consteval}\br \terminal{inline} \end{bnf} @@ -269,9 +270,11 @@ same type. \pnum -Each \grammarterm{decl-specifier} shall appear at most once in a complete -\grammarterm{decl-specifier-seq}, except that -\tcode{long} may appear twice. +Each \grammarterm{decl-specifier} +shall appear at most once in a complete \grammarterm{decl-specifier-seq}, +except that \tcode{long} may appear twice. +The \tcode{constexpr} and \tcode{consteval} \grammarterm{decl-specifier}{s} +shall not both appear in a \grammarterm{decl-specifier-seq}. \pnum \indextext{ambiguity!declaration type}% @@ -736,17 +739,21 @@ \indextext{specifier!\idxcode{constexpr}} \pnum -The \tcode{constexpr} specifier shall be applied only to the definition of -a variable or variable template or -the declaration of a -function or function template. -A function or static data member declared with the \tcode{constexpr} -specifier is implicitly an inline function or variable\iref{dcl.inline}. +The \tcode{constexpr} specifier shall be applied only to +the definition of a variable or variable template or +the declaration of a function or function template. +The \tcode{consteval} specifier shall be applied only to +the declaration of a function or function template. +A function or static data member +declared with the \tcode{constexpr} or \tcode{consteval} specifier +is implicitly an inline function or variable\iref{dcl.inline}. If any declaration of a function or function template has -a \tcode{constexpr} specifier, -then all its declarations shall contain the \tcode{constexpr} specifier. \begin{note} An -explicit specialization can differ from the template declaration with respect to the -\tcode{constexpr} specifier. \end{note} +a \tcode{constexpr} or \tcode{consteval} specifier, +then all its declarations shall contain the same specifier. +\begin{note} +An explicit specialization can differ from the template declaration +with respect to the \tcode{constexpr} or \tcode{consteval} specifier. +\end{note} \begin{note} Function parameters cannot be declared \tcode{constexpr}.\end{note} \begin{example} @@ -776,12 +783,17 @@ \end{example} \pnum -A \tcode{constexpr} specifier used in the declaration of a function that is not a -constructor declares that -function to be a \defnx{constexpr function}{specifier!\idxcode{constexpr}!function}. Similarly, a -\tcode{constexpr} specifier used in -a constructor declaration declares that constructor to be a -\defnx{constexpr constructor}{specifier!\idxcode{constexpr}!constructor}. +A \tcode{constexpr} or \tcode{consteval} specifier +used in the declaration of a function that is not a constructor +declares that function to be +a \defnx{constexpr function}{specifier!\idxcode{constexpr}!function}. +Similarly, a \tcode{constexpr} or \tcode{consteval} specifier used in +a constructor declaration declares that constructor to be +a \defnx{constexpr constructor}{specifier!\idxcode{constexpr}!constructor}. +A function or constructor declared with the \tcode{consteval} specifier +is called an \defn{immediate function}. +A destructor, an allocation function, or a deallocation function +shall not be declared with the \tcode{consteval} specifier. \pnum \indextext{specifier!\idxcode{constexpr}!function} @@ -946,8 +958,9 @@ \end{itemize} \pnum -The \tcode{constexpr} specifier has no -effect on the type of a constexpr function or a constexpr constructor. \begin{example} +The \tcode{constexpr} and \tcode{consteval} specifiers have no +effect on the type of a constexpr function or a constexpr constructor. +\begin{example} \begin{codeblock} constexpr int bar(int x, int y) // OK { return x + y + x*y; } @@ -1430,7 +1443,8 @@ \end{note} \pnum -If the operand of a \grammarterm{decltype-specifier} is a prvalue, +If the operand of a \grammarterm{decltype-specifier} is a prvalue +and is not a (possibly parenthesized) immediate invocation\iref{expr.const}, the temporary materialization conversion is not applied\iref{conv.rval} and no result object is provided for the prvalue. The type of the prvalue may be incomplete or an abstract class type. @@ -5880,9 +5894,9 @@ \pnum An explicitly-defaulted function that is not defined as deleted may be declared -\tcode{constexpr} only if it would have been implicitly declared as -\tcode{constexpr}. If -a function is explicitly defaulted on its first declaration, +\tcode{constexpr} or \tcode{consteval} only +if it would have been implicitly declared as \tcode{constexpr}. +If a function is explicitly defaulted on its first declaration, it is implicitly considered to be \tcode{constexpr} if the implicit declaration would be. diff --git a/source/expressions.tex b/source/expressions.tex index 7e9a29bbb9..4a84068a99 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -1266,6 +1266,12 @@ \end{example} \end{itemize} +\pnum +An \grammarterm{id-expression} +that denotes an immediate function\iref{dcl.constexpr} +shall appear as a subexpression of an immediate invocation or +in an immediate function context\iref{expr.const}. + \pnum An \grammarterm{id-expression} that denotes the specialization of a concept\iref{temp.concept} @@ -1554,7 +1560,7 @@ \pnum In the \grammarterm{decl-specifier-seq} of the \grammarterm{lambda-declarator}, each \grammarterm{decl-specifier} -shall either be \tcode{mutable} or \tcode{constexpr}. +shall be one of \tcode{mutable}, \tcode{constexpr}, or \tcode{consteval}. \begin{note} The trailing \grammarterm{requires-clause} is described in \ref{dcl.decl}. \end{note} @@ -1680,8 +1686,12 @@ The function call operator or any given operator template specialization is a constexpr function if either the corresponding \grammarterm{lambda-expression}{'s} -\grammarterm{parameter-declaration-clause} is followed by \tcode{constexpr}, or +\grammarterm{parameter-declaration-clause} +is followed by \tcode{constexpr} or \tcode{consteval}, or it satisfies the requirements for a constexpr function\iref{dcl.constexpr}. +It is an immediate function\iref{dcl.constexpr} +if the corresponding \grammarterm{lambda-expression}{'s} +\grammarterm{parameter-declaration-clause} is followed by \tcode{consteval}. \begin{note} Names referenced in the \grammarterm{lambda-declarator} are looked up in the context in which the \grammarterm{lambda-expression} appears. \end{note} @@ -1759,7 +1769,9 @@ is the address of a function \tcode{F} that, when invoked, has the same effect as invoking the closure type's function call operator. \tcode{F} is a constexpr function -if the function call operator is a constexpr function. +if the function call operator is a constexpr function +and is an immediate function +if the function call operator is an immediate function. For a generic lambda with no \grammarterm{lambda-capture}, the closure type has a conversion function template to pointer to function. The conversion function template has the same invented @@ -6807,8 +6819,12 @@ if the value is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object\iref{expr.add}, - the address of a function, - or a null pointer value, and + the address of a non-immediate function, + or a null pointer value, + + \item + if the value is of pointer-to-member-function type, + it does not designate an immediate function, and \item if the value is an object of class or array type, @@ -6818,8 +6834,18 @@ \defnx{permitted result of a constant expression}{constant expression!permitted result of} if it is an object with static storage duration that is either not a temporary object or is -a temporary object whose value satisfies the above constraints, or it is a -function. +a temporary object whose value satisfies the above constraints, or +it is a non-immediate function. +\begin{example} +\begin{codeblock} +consteval int f() { return 42; } +consteval auto g() { return f; } +consteval int h(int (*p)() = g()) { return p(); } +constexpr int r = h(); // OK +constexpr auto e = g(); // ill-formed: a pointer to an immediate function is + // not a permitted result of a constant expression +\end{codeblock} +\end{example} \pnum \begin{note} Since this document @@ -6840,15 +6866,31 @@ It is unspecified whether the value of \tcode{f()} will be \tcode{true} or \tcode{false}. \end{example} \end{note}% +\pnum +An expression or conversion is in an \defn{immediate function context} +if it is potentially evaluated and +its innermost non-block scope is +a function parameter scope of an immediate function. +An expression or conversion is an \defn{immediate invocation} +if it is an explicit or implicit invocation of an immediate function and +is not in an immediate function context. +An immediate invocation shall be a constant expression. +\begin{note} +An immediate invocation is evaluated even in an unevaluated operand. +\end{note} + \pnum \indextext{expression!potentially constant evaluated}% -An expression is \defn{potentially constant evaluated} +An expression or conversion is \defn{potentially constant evaluated} if it is: \begin{itemize} \item a potentially-evaluated expression\iref{basic.def.odr}, +\item +an immediate invocation, + \item a \grammarterm{constraint-expression}, including one formed from the \grammarterm{constraint-logical-or-expression} @@ -6886,4 +6928,21 @@ is of non-volatile const-qualified integral type or of reference type. \end{itemize} +\begin{example} +\begin{codeblock} +struct N { + constexpr N() {} + N(N const&) = delete; +}; +template constexpr void bad_assert_copyable() { T t; T t2 = t; } +using ineffective = decltype(bad_assert_copyable()); + // \tcode{bad_assert_copyable} is not needed for constant evaluation + // (and thus not instantiated) +template consteval void assert_copyable() { T t; T t2 = t; } +using check = decltype(assert_copyable()); + // error: \tcode{assert_copyable} is instantiated (because it is needed for constant + // evaluation), but the attempt to copy \tcode{t} is ill-formed +\end{codeblock} +\end{example} + \indextext{expression|)} diff --git a/source/lex.tex b/source/lex.tex index 16478475c7..4650f265c4 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -687,8 +687,9 @@ \tcode{class} \\ \tcode{concept} \\ \tcode{const} \\ -\tcode{constexpr} \\ +\tcode{consteval} \\ \columnbreak +\tcode{constexpr} \\ \tcode{const_cast} \\ \tcode{continue} \\ \tcode{decltype} \\ @@ -704,8 +705,8 @@ \tcode{extern} \\ \tcode{false} \\ \tcode{float} \\ -\tcode{for} \\ \columnbreak +\tcode{for} \\ \tcode{friend} \\ \tcode{goto} \\ \tcode{if} \\ @@ -721,8 +722,8 @@ \tcode{private} \\ \tcode{protected} \\ \tcode{public} \\ -\tcode{register} \\ \columnbreak +\tcode{register} \\ \tcode{reinterpret_cast} \\ \tcode{requires} \\ \tcode{return} \\ @@ -738,8 +739,8 @@ \tcode{this} \\ \tcode{thread_local} \\ \tcode{throw} \\ -\tcode{true} \\ \columnbreak +\tcode{true} \\ \tcode{try} \\ \tcode{typedef} \\ \tcode{typeid} \\ diff --git a/source/macros.tex b/source/macros.tex index 3e54e2b3e4..352163c088 100644 --- a/source/macros.tex +++ b/source/macros.tex @@ -335,14 +335,16 @@ \newcommand{\range}[2]{\Range{[}{)}{#1}{#2}} %% Change descriptions -\newcommand{\diffdef}[1]{\hfill\break\textbf{#1:}\space} +\newcommand{\diffhead}[1]{\textbf{#1:}\space} +\newcommand{\diffdef}[1]{\hfill\break\diffhead{#1}} \newcommand{\diffref}[1]{\pnum\textbf{Affected subclause:} \ref{#1}} \newcommand{\diffrefs}[2]{\pnum\textbf{Affected subclauses:} \ref{#1}, \ref{#2}} % \nodiffref swallows a following \change and removes the preceding line break. -\def\nodiffref\change{\pnum\textbf{Change:}\space} +\def\nodiffref\change{\pnum\diffhead{Change}} \newcommand{\change}{\diffdef{Change}} \newcommand{\rationale}{\diffdef{Rationale}} \newcommand{\effect}{\diffdef{Effect on original feature}} +\newcommand{\effectafteritemize}{\diffhead{Effect on original feature}} \newcommand{\difficulty}{\diffdef{Difficulty of converting}} \newcommand{\howwide}{\diffdef{How widely used}} diff --git a/source/templates.tex b/source/templates.tex index 4b0de15b9d..19a2f09108 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -6146,7 +6146,7 @@ member function of a class template, or variable template shall not -use the \tcode{inline} or \tcode{constexpr} specifiers. +use the \tcode{inline}, \tcode{constexpr}, or \tcode{consteval} specifiers. \pnum The syntax for explicit instantiation is: