From e3f552ff09eb42cec8ee0590e4b8aa716996b282 Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Mon, 17 Feb 2025 08:53:49 -0800 Subject: [PATCH 1/4] P2841R7 Concept and variable-template template-parameters Editorial notes: * [temp.param]temp.arg.type] Some instructions do not apply due to more recent changes in the wording. * [temp.param] Added a reference for concept-dependent to where it's defined. * [temp.param] Move reference after "concept-dependent constraint". * [temp.constr.concept] Replace "may" with "might" inside note. * [temp.constr.concept] Add a reference for "normal form". * [temp.func.order] Move note to remain with the relevant context. --- source/basic.tex | 27 +- source/declarations.tex | 8 +- source/preprocessor.tex | 1 + source/templates.tex | 583 +++++++++++++++++++++++++++++----------- 4 files changed, 454 insertions(+), 165 deletions(-) diff --git a/source/basic.tex b/source/basic.tex index b794205e59..152a9eff7f 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -74,10 +74,16 @@ \item \grammarterm{using-declarator}\iref{namespace.udecl}, \item -\grammarterm{parameter-declaration}\iref{dcl.fct}, +\grammarterm{parameter-declaration}\iref{dcl.fct,temp.param}, \item \grammarterm{type-parameter}\iref{temp.param}, \item +\grammarterm{type-tt-parameter}\iref{temp.param}, +\item +\grammarterm{variable-tt-parameter}\iref{temp.param}, +\item +\grammarterm{concept-tt-parameter}\iref{temp.param}, +\item \grammarterm{elaborated-type-specifier} that introduces a name\iref{dcl.type.elab}, \item @@ -1506,7 +1512,11 @@ \rSec2[basic.scope.temp]{Template parameter scope}% \pnum -Each template \grammarterm{template-parameter} introduces +Each +\grammarterm{type-tt-parameter}, +\grammarterm{variable-tt-parameter}, and +\grammarterm{concept-tt-parameter} +introduces a \defnadj{template parameter}{scope} that includes the \grammarterm{template-head} of the \grammarterm{template-parameter}. @@ -2051,7 +2061,7 @@ then lookup for the name also includes the result of \defnadj{argument-dependent}{lookup} in a set of associated namespaces that depends on the types of the arguments -(and for template template arguments, the namespace of the template argument), +(and for type template template arguments, the namespace of the template argument), as specified below. \begin{example} \begin{codeblock} @@ -2119,7 +2129,7 @@ to be considered. The set of entities is determined entirely by the types of the function arguments -(and any template template arguments). +(and any type template template arguments). Any \grammarterm{typedef-name}s and \grammarterm{using-declaration}{s} used to specify the types do not contribute to this set. @@ -2139,11 +2149,14 @@ the entities associated with the types of the template arguments provided for template type parameters; -the templates used as template template arguments; and -the classes of which any member templates used as template template +the templates used as type template template arguments; and +the classes of which any member templates used as type template template arguments are members. \begin{note} -Constant template arguments do not +Constant template arguments, +variable template template arguments, and +concept template arguments +do not contribute to the set of associated entities. \end{note} diff --git a/source/declarations.tex b/source/declarations.tex index 7cb48705c3..7e297cde17 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -778,7 +778,7 @@ \indextext{class name!\idxcode{typedef}}% A \grammarterm{simple-template-id} is only a \grammarterm{typedef-name} if its \grammarterm{template-name} names -an alias template or a template template parameter. +an alias template or a type template template parameter. \begin{note} A \grammarterm{simple-template-id} that names a class template specialization is a \grammarterm{class-name}\iref{class.name}. @@ -4041,7 +4041,7 @@ An abbreviated function template is equivalent to a function template\iref{temp.fct} whose \grammarterm{template-parameter-list} includes -one invented type \grammarterm{template-parameter} +one invented \grammarterm{type-parameter} for each generic parameter type placeholder of the function declaration, in order of appearance. For a \grammarterm{placeholder-type-specifier} of the form \keyword{auto}, @@ -4051,7 +4051,7 @@ \grammarterm{type-constraint} \keyword{auto}, the invented parameter is a \grammarterm{type-parameter} with that \grammarterm{type-constraint}. -The invented type \grammarterm{template-parameter} is +The invented \grammarterm{type-parameter} declares a template parameter pack if the corresponding \grammarterm{parameter-declaration} declares a function parameter pack. @@ -4060,7 +4060,7 @@ The adjusted function parameters of an abbreviated function template are derived from the \grammarterm{parameter-declaration-clause} by replacing each occurrence of a placeholder with -the name of the corresponding invented \grammarterm{template-parameter}. +the name of the corresponding invented \grammarterm{type-parameter}. \begin{example} \begin{codeblock} template concept C1 = /* ... */; diff --git a/source/preprocessor.tex b/source/preprocessor.tex index 254488a635..53829ff929 100644 --- a/source/preprocessor.tex +++ b/source/preprocessor.tex @@ -1906,6 +1906,7 @@ \defnxname{cpp_static_assert} & \tcode{202306L} \\ \rowsep \defnxname{cpp_static_call_operator} & \tcode{202207L} \\ \rowsep \defnxname{cpp_structured_bindings} & \tcode{202411L} \\ \rowsep +\defnxname{cpp_template_parameters} & \tcode{202502L} \\ \rowsep \defnxname{cpp_template_template_args} & \tcode{201611L} \\ \rowsep \defnxname{cpp_threadsafe_static_init} & \tcode{200806L} \\ \rowsep \defnxname{cpp_trivial_union} & \tcode{202502L} \\ \rowsep diff --git a/source/templates.tex b/source/templates.tex index f2e7334afe..b34b37e515 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -237,7 +237,10 @@ \begin{bnf} \nontermdef{template-parameter}\br type-parameter\br - parameter-declaration + parameter-declaration\br + type-tt-parameter\br + variable-tt-parameter\br + concept-tt-parameter \end{bnf} \begin{bnf} @@ -245,9 +248,7 @@ type-parameter-key \opt{\terminal{...}} \opt{identifier}\br type-parameter-key \opt{identifier} \terminal{=} type-id\br type-constraint \opt{\terminal{...}} \opt{identifier}\br - type-constraint \opt{identifier} \terminal{=} type-id\br - template-head type-parameter-key \opt{\terminal{...}} \opt{identifier}\br - template-head type-parameter-key \opt{identifier} \terminal{=} id-expression + type-constraint \opt{identifier} \terminal{=} type-id \end{bnf} \begin{bnf} @@ -262,6 +263,30 @@ \opt{nested-name-specifier} concept-name \terminal{<} \opt{template-argument-list} \terminal{>} \end{bnf} +\begin{bnf} +\nontermdef{type-tt-parameter}\br + template-head type-parameter-key \opt{\terminal{...}} \opt{identifier}\br + template-head type-parameter-key \opt{identifier} \opt{type-tt-parameter-default} +\end{bnf} + +\begin{bnf} +\nontermdef{type-tt-parameter-default}\br + \terminal{=} \opt{nested-name-specifier} template-name\br + \terminal{=} nested-name-specifier \terminal{template} template-name +\end{bnf} + +\begin{bnf} +\nontermdef{variable-tt-parameter}\br + template-head \terminal{auto} \opt{\terminal{...}} \opt{identifier}\br + template-head \terminal{auto} \opt{identifier} \terminal{=} \opt{nested-name-specifier} template-name +\end{bnf} + +\begin{bnf} +\nontermdef{concept-tt-parameter}\br + \terminal{template} \terminal{<} template-parameter-list \terminal{>} \terminal{concept} \opt{\terminal{...}} \opt{identifier}\br + \terminal{template} \terminal{<} template-parameter-list \terminal{>} \terminal{concept} \opt{identifier} \terminal{=} \opt{nested-name-specifier} template-name +\end{bnf} + \indextext{component name}% The component names of a \grammarterm{type-constraint} are its \grammarterm{concept-name} and @@ -269,12 +294,81 @@ \begin{note} The \tcode{>} token following the \grammarterm{template-parameter-list} of a -\grammarterm{type-parameter} +\grammarterm{type-tt-parameter}, +\grammarterm{variable-tt-parameter}, or +\grammarterm{concept-tt-parameter} can be the product of replacing a \tcode{>>} token by two consecutive \tcode{>} tokens\iref{temp.names}. \end{note} +\pnum +%FIXME: "is" or "shall be"? i.e., what if it's not? +%FIXME: Note: we don't appear to ever define what a "template parameter" is; +%FIXME: is this supposed to be the definition for template parameter? +A template parameter is of one of the following kinds: +\begin{itemize} +\item +A \defnadj{type}{template parameter} is +a template parameter introduced by a \grammarterm{type-parameter}. +\item +A \defnadj{constant}{template parameter} is +a template parameter introduced by a \grammarterm{parameter-declaration}. +\item +A \defnadj{type template}{template parameter} is +a template parameter introduced by a \grammarterm{type-tt-parameter}. +\item +A \defnadj{variable template}{template parameter} is +a template parameter introduced by a \grammarterm{variable-tt-parameter}. +\item +A \defnadj{concept}{template parameter} is +a template parameter introduced by a \grammarterm{concept-tt-parameter}. +\end{itemize} + +\pnum +Type template template parameters, +variable template template parameters, and +concept template parameters +are collectively referred to as \defnadj{template}{template parameters}. + +\pnum +A concept template parameter shall not have +associated constraints\iref{temp.constr.decl}. + +\pnum +If a \grammarterm{template-parameter} is +a \grammarterm{parameter-declaration} that declares a pack\iref{dcl.fct}, or +otherwise has an ellipsis prior to its optional \grammarterm{identifier}, +then the \grammarterm{template-parameter} +declares a template parameter pack\iref{temp.variadic}. +A template parameter pack that is a \grammarterm{parameter-declaration} whose type +contains one or more unexpanded packs is a pack expansion. Similarly, +a template parameter pack that is a template template parameter with a +\grammarterm{template-parameter-list} containing one or more unexpanded +packs is a pack expansion. +A type parameter pack with a \grammarterm{type-constraint} that +contains an unexpanded parameter pack is a pack expansion. +A template parameter pack that is a pack +expansion shall not expand a template parameter pack declared in the same +\grammarterm{template-parameter-list}. +\begin{example} +\begin{codeblock} +template // \tcode{Types} is a template type parameter pack + class Tuple; // but not a pack expansion + +template // \tcode{Dims} is a constant template parameter pack + struct multi_array; // but not a pack expansion + +template + struct value_holder { + template struct apply { }; // \tcode{Values} is a constant template parameter pack + }; // and a pack expansion + +template // error: \tcode{Values} expands template type parameter + struct static_array; // pack \tcode{T} within the same template parameter list +\end{codeblock} +\end{example} + \pnum There is no semantic difference between \keyword{class} @@ -290,13 +384,6 @@ followed by a \grammarterm{qualified-id} denotes the type in a -\begin{footnote} -The terms -\term{constant template parameter} -and -\term{constant template argument} -are used to refer to non-type, non-template parameters and arguments. -\end{footnote} \grammarterm{parameter-declaration}. A \grammarterm{template-parameter} of the form \keyword{class} \grammarterm{identifier} is a \grammarterm{type-parameter}. @@ -320,34 +407,22 @@ declaration. \pnum -The \grammarterm{identifier} in a \grammarterm{type-parameter} is not looked up. -A \grammarterm{type-parameter} -whose \grammarterm{identifier} does not follow an ellipsis -defines its -\grammarterm{identifier} -to be a -\grammarterm{typedef-name} -(if declared without -\keyword{template}) -or -\grammarterm{template-name} -(if declared with -\keyword{template}) +The \grammarterm{identifier} in +a \grammarterm{template-parameter} denoting a type or template +is not looked up. +An \grammarterm{identifier} that does not follow an ellipsis +is defined to be +\begin{itemize} +\item +a \grammarterm{typedef-name} for a \grammarterm{type-parameter}, +\item +a \grammarterm{template-name} for a \grammarterm{variable-tt-parameter}, +\item +a \grammarterm{template-name} for a \grammarterm{type-tt-parameter}, or +\item +a \grammarterm{concept-name} for a \grammarterm{concept-tt-parameter}, +\end{itemize} in the scope of the template declaration. -\begin{note} -A template argument can be a class template or alias template. -For example, - -\begin{codeblock} -template class myarray { @\commentellip@ }; - -template class C = myarray> -class Map { - C key; - C value; -}; -\end{codeblock} -\end{note} \pnum A \grammarterm{type-constraint} \tcode{Q} that designates a concept \tcode{C} @@ -591,39 +666,15 @@ } \end{codeblock} \end{example} - -\pnum -If a \grammarterm{template-parameter} is a -\grammarterm{type-parameter} with an ellipsis prior to its -optional \grammarterm{identifier} or is a -\grammarterm{parameter-declaration} that declares a -pack\iref{dcl.fct}, then the \grammarterm{template-parameter} -is a template parameter pack\iref{temp.variadic}. -A template parameter pack that is a \grammarterm{parameter-declaration} whose type -contains one or more unexpanded packs is a pack expansion. Similarly, -a template parameter pack that is a template template parameter with a -\grammarterm{template-parameter-list} containing one or more unexpanded -packs is a pack expansion. -A type parameter pack with a \grammarterm{type-constraint} that -contains an unexpanded parameter pack is a pack expansion. -A template parameter pack that is a pack -expansion shall not expand a template parameter pack declared in the same -\grammarterm{template-parameter-list}. +The associated constraints of a template template parameter +shall not contain a concept-dependent constraint\iref{temp.constr.concept}. \begin{example} \begin{codeblock} -template // \tcode{Types} is a template type parameter pack - class Tuple; // but not a pack expansion - -template // \tcode{Dims} is a constant template parameter pack - struct multi_array; // but not a pack expansion - -template - struct value_holder { - template struct apply { }; // \tcode{Values} is a constant template parameter pack - }; // and a pack expansion - -template // error: \tcode{Values} expands template type parameter - struct static_array; // pack \tcode{T} within the same template parameter list +template< + template concept C, + template class TT // error: \tcode{C} forms a concept-dependent constraint +> +struct A {}; \end{codeblock} \end{example} @@ -660,8 +711,8 @@ \nontermdef{template-argument}\br constant-expression\br type-id\br - id-expression\br - braced-init-list + \opt{nested-name-specifier} template-name\br + nested-name-specifier \terminal{template} template-name \end{bnf} \pnum @@ -915,11 +966,6 @@ \pnum \indextext{argument!template}% -There are three forms of -\grammarterm{template-argument}, -corresponding to the three forms of -\grammarterm{template-parameter}: -type, constant and template. The type and form of each \grammarterm{template-argument} specified in a @@ -1158,7 +1204,7 @@ (for a default template argument) an \grammarterm{initializer-clause}. \end{note} If the parameter type thus deduced is not permitted -for a template parameter declaration\iref{temp.param}, +for a constant template parameter\iref{temp.param}, the program is ill-formed. \pnum @@ -1337,8 +1383,13 @@ \grammarterm{template-argument} for a template template parameter -shall be the name of a class template or an alias template, expressed as -\grammarterm{id-expression}. +shall be the name of a template. +For a \grammarterm{type-tt-parameter}, +the name shall denote a class template or alias template. +For a \grammarterm{variable-tt-parameter}, +the name shall denote a variable template. +For a \grammarterm{concept-tt-parameter}, +the name shall denote a concept. Only primary templates are considered when matching the template template argument with the corresponding parameter; partial specializations are not considered even if their parameter lists match that of the template template @@ -1368,9 +1419,27 @@ \end{codeblock} \end{example} +\pnum +A template template parameter \tcode{P} and +a \grammarterm{template-argument} \tcode{A} are +\defnx{compatible}{compatible!template template parameter and template argument} +if +\begin{itemize} +\item +\tcode{A} denotes a class template or an alias template and +\tcode{P} is a type template parameter, +\item +\tcode{A} denotes a variable template and +\tcode{P} is a variable template parameter, or +\item +\tcode{A} denotes a concept and +\tcode{P} is a concept template parameter. +\end{itemize} + \pnum A template \grammarterm{template-argument} \tcode{A} matches a template template parameter \tcode{P} when +\tcode{A} and \tcode{P} are compatible and \tcode{P} is at least as specialized as \tcode{A}, ignoring constraints on \tcode{A} if \tcode{P} is unconstrained. If \tcode{P} contains a template parameter pack, then \tcode{A} also matches \tcode{P} @@ -1500,12 +1569,13 @@ A \defn{constraint} is a sequence of logical operations and operands that specifies requirements on template arguments. The operands of a logical operation are constraints. -There are four different kinds of constraints: +There are five different kinds of constraints: \begin{itemize} \item conjunctions\iref{temp.constr.op}, \item disjunctions\iref{temp.constr.op}, -\item atomic constraints\iref{temp.constr.atomic}, and -\item fold expanded constraints\iref{temp.constr.fold}. +\item atomic constraints\iref{temp.constr.atomic}, +\item fold expanded constraints\iref{temp.constr.fold}, and +\item concept-dependent constraints\iref{temp.constr.concept}. \end{itemize} \pnum @@ -1740,6 +1810,70 @@ \end{codeblock} \end{example} +\rSec3[temp.constr.concept]{Concept-dependent constraints} + +\pnum +A \defnadj{concept-dependent}{constraint} \tcode{CD} is +an atomic constraint whose expression is a concept-id \tcode{CI} whose +\grammarterm{concept-name} names a dependent concept named \tcode{C}. + +\pnum +To determine if \tcode{CD} is satisfied, +the parameter mapping and template arguments are first +substituted into \tcode{C}. +If substitution results in an invalid concept-id in +the immediate context of the constraint\iref{temp.deduct.general}, +the constraint is not satisfied. +Otherwise, let \tcode{CI$'$} be +the normal form\iref{temp.constr.normal} of the concept-id +after substitution of \tcode{C}. +\begin{note} +Normalization of \tcode{CI} might be ill-formed; no diagnostics is required. +\end{note} + +\pnum +To form \tcode{CI$''$}, +each appearance of \tcode{C}{'s} template parameters in +the parameter mappings of the atomic constraints +(including concept-dependent constraints) +in \tcode{CI$'$} +is substituted with their respective arguments from +the parameter mapping of \tcode{CD} and the arguments of \tcode{CI}. + +\pnum +%FIXME: What "constraint"? CD? +The constraint is satisfied if \tcode{CI$''$} is satisfied. +\begin{note} +Checking whether \tcode{CI$''$} is satisfied +can lead to further normalization of concept-dependent constraints. +\end{note} +%FIXME: "_" in the example below is not a valid identifier. +\begin{example} +\begin{codeblock} +template +concept C = true; + +template concept CC> +concept D = CC; + +template concept CT, + template concept> concept CU> +int f() requires CU; +int _ = f(); +\end{codeblock} +In this example, the associated constraint of \tcode{f} +is a concept-dependent constraint $CI$ +whose expression is the concept-id \tcode{CU} with the mapping +$\tcode{T} \mapsto \tcode{T}, \tcode{CT} \mapsto \tcode{CT}, \tcode{CU} \mapsto \tcode{CU}$.\\ +$CI'$ is the result of substituting \tcode{D} into $CI$.\\ +We consider the normal form $CI''$ of \tcode{D}, +which is \tcode{CC} with the mapping +$\tcode{T} \mapsto \tcode{T}, \tcode{CC} \mapsto \tcode{CC}$.\\ +By recursion, \tcode{C} is substituted in \tcode{CC} and then +normalized to the atomic constraint \tcode{true}, which is satisfied. +\end{example} + \rSec3[temp.constr.fold]{Fold expanded constraint} \pnum @@ -1930,13 +2064,30 @@ the normal forms of \tcode{E1} and \tcode{E2}. \item -The normal form of a concept-id \tcode{C} -is the normal form of the \grammarterm{constraint-expression} of \tcode{C}, -after substituting \tcode{A$_1$, A$_2$, $\dotsc$, A$_n$} for -\tcode{C}{'s} respective template parameters in the -parameter mappings in each atomic constraint. +For a concept-id \tcode{C} termed \tcode{CI}: +\begin{itemize} +\item +If \tcode{C} names a dependent concept, +the normal form of \tcode{CI} is a concept-dependent constraint +whose concept-id is \tcode{CI} and +whose parameter mapping is the identity mapping. +\item +Otherwise, to form \tcode{CE}, +%FIXME: We're saying any Ai can be used to form CE. Do we have to try all +%FIXME: the Ais to check for ill-formedness or just the random one we picked? +%FIXME: Don't we want to form a CEi for each Ai? +any non-dependent concept template argument \tcode{A$_i$} +is substituted into the \grammarterm{constraint-expression} of \tcode{C}. +If any such substitution results in an invalid concept-id, +the program is ill-formed; no diagnostic is required. +The normal form of \tcode{CI} is the result of substituting, +in the normal form \tcode{N} of \tcode{CE}, +appearances of \tcode{C}{'s} template parameters +in the parameter mappings of the atomic constraints in \tcode{N} +with their respective arguments from \tcode{C}. If any such substitution results in an invalid type or expression, the program is ill-formed; no diagnostic is required. +\end{itemize} \begin{example} \begin{codeblock} template concept A = T::value || true; @@ -1957,38 +2108,50 @@ \end{example} \item -For a \grammarterm{fold-operator}\iref{expr.prim.fold} -that is either \tcode{\&\&} or \tcode{||}, -the normal form of an expression -\tcode{( ... \grammarterm{fold-operator} E )} is the normal form of -\tcode{( E \grammarterm{fold-operator} ... )}. - -\item -For a \grammarterm{fold-operator} -that is either \tcode{\&\&} or \tcode{||}, -the normal form of an expression -\tcode{( E1 \grammarterm{fold-operator} ... \grammarterm{fold-operator} E2 )} -is the normal form of -\begin{itemize} -\item -\tcode{( E1 \grammarterm{fold-operator} ... ) \grammarterm{fold-operator} E2} -if \tcode{E1} contains an unexpanded pack, or -\item -\tcode{E1 \grammarterm{fold-operator} ( E2 \grammarterm{fold-operator} ... )} -otherwise. -\end{itemize} - -\item -The normal form of \tcode{( E \&\& ... )} is -a fold expanded constraint\iref{temp.constr.fold} -whose constraint is the normal form of \tcode{E} and -whose \grammarterm{fold-operator} is \tcode{\&\&}. - -\item -The normal form of \tcode{( E || ... )} is -a fold expanded constraint -whose constraint is the normal form of \tcode{E} and -whose \grammarterm{fold-operator} is \tcode{||}. +For a \grammarterm{fold-operator} \tcode{Op} \iref{expr.prim.fold} +that is either \tcode{\&\&} or \tcode{||}: + \begin{itemize} + \item + The normal form of an expression \tcode{( ... Op E )} + is the normal form of \tcode{( E Op ... )}. + \item + The normal form of an expression \tcode{( E1 Op ... Op E2 )} + is the normal form of + \begin{itemize} + \item + \tcode{( E1 Op ... ) Op E2} if \tcode{E1} contains an unexpanded pack, or + \item + \tcode{E1 Op ( E2 Op ... )} otherwise. + \end{itemize} + \item + The normal form of an expression \tcode{F} of the form \tcode{( E Op ... )} + is as follows:\\ + If \tcode{E} names any unexpanded concept template parameter pack, + it shall not name any unexpanded template parameter pack of another kind. + Let \tcode{E$'$} be the normal form of \tcode{E}. + \begin{itemize} + \item + If \tcode{E} names + any unexpanded concept template parameter pack \tcode{P$_k$} that + has corresponding template arguments in + the parameter mapping of any atomic constraint + (including concept-dependent constraints) of \tcode{E$'$}, + the number of arguments specified for all such \tcode{P$_k$} + shall be the same number $N$. + The normal form of \tcode{F} is the normal form of + \tcode{E$_0$ Op $\dotsb$ Op E$_{N-1}$} + after substituting in \tcode{E$_i$} + the respective $i^\text{th}$ concept argument of each \tcode{P$_k$}. + If any such substitution results in an invalid type or expression, + the program is ill-formed; no diagnostic is required. + \item + Otherwise, + the normal form of \tcode{F} is + a fold expanded constraint\iref{temp.constr.fold} whose + constraint is \tcode{E$'$} and whose + \grammarterm{fold-operator} is \tcode{Op}. + \end{itemize} + \end{itemize} \item The normal form of any other expression \tcode{E} is @@ -2031,6 +2194,64 @@ The associated constraints of \#3 are \tcode{requires (T x) \{ ++x; \}} (with mapping $\tcode{T} \mapsto \tcode{U}$). \end{example} + +\begin{example} +\begin{codeblock} +template +concept C = true; +template concept CT> +concept CC = CT; + +template concept> concept CT> + void f() requires CT; +template + void g() requires CC; +\end{codeblock} +The normal form of the associated constraints of \tcode{f} is +the concept-dependent constraint \tcode{CT}.\\ +The normal form of the associated constraints of \tcode{g} is +the atomic constraint \tcode{true}. +\end{example} + +\begin{example} +\begin{codeblock} +template +concept A = true; +template +concept B = A && true; // \tcode{B} subsumes \tcode{A} +template +concept C = true; +template +concept D = C && true; // \tcode{D} subsumes \tcode{C} + +template concept... CTs> +concept all_of = (CTs && ...); + +template requires all_of + constexpr int f(T) { return 1; } // \#1 +template requires all_of + constexpr int f(T) { return 2; } // \#2 + +static_assert(f(1) == 2); // ok +\end{codeblock} +The normal form of \tcode{all_of} is +the conjunction of the normal forms of \tcode{A} and \tcode{C}.\\ +Similarly, the normal form of \tcode{all_of} is +the conjunction of the normal forms of \tcode{B} and \tcode{D}.\\ +\#2 therefore is more constrained than \#1. +\end{example} + +\begin{example} +\begin{codeblock} +template concept> +struct wrapper {}; + +template concept... CTs> + int f(wrapper...) requires (CTs && ...); // error: the fold expression expands mixed kind template parameters +\end{codeblock} +\end{example} + \indextext{constraint!normalization|)} \rSec2[temp.constr.order]{Partial ordering by constraints} @@ -2103,6 +2324,14 @@ \end{itemize} \end{note} +\pnum +The associated constraints \tcode{C} of a declaration \tcode{D} +\indextext{subsumption!eligible for}% +are \defnx{eligible for subsumption}{eligible!for subsumption} +%%% FIXME: This "definiton" needs work. Do we mean: +%%% "if C can be subsumed and C does not contain a concept-dependent constraint"? +unless \tcode{C} contains a concept-dependent constraint. + %%% FIXME: We need to substitute the deductions from partial ordering %%% into the constraints before comparing them, otherwise they will be %%% referring to unrelated template parameters. @@ -2112,7 +2341,8 @@ a declaration \tcode{D2} if \begin{itemize} \item \tcode{D1} and \tcode{D2} are both constrained declarations and -\tcode{D1}'s associated constraints subsume those of \tcode{D2}; or +\tcode{D1}'s associated constraints +are eligible for subsumption and subsume those of \tcode{D2}; or \item \tcode{D2} has no associated constraints. \end{itemize} @@ -2138,6 +2368,21 @@ g(0); // selects \#4 \end{codeblock} \end{example} +\begin{example} +\begin{codeblock} +template concept CT, typename T> +struct S {}; +template +concept A = true; + +template concept X, typename T> +int f(S) requires A { return 42; } // \#1 +template concept X, typename T> +int f(S) requires X { return 43; } // \#2 + +f(S{}); // ok, select \#1 because \#2 is not eligible for subsumption +\end{codeblock} +\end{example} \pnum A non-template function \tcode{F1} is \defn{more partial-ordering-constrained} @@ -2885,6 +3130,14 @@ \item if the template parameter pack is a \grammarterm{type-parameter}; the pattern is the corresponding \grammarterm{type-parameter} +without the ellipsis; + +\item +if the template parameter pack is a template template parameter; +the pattern is the corresponding +\grammarterm{type-tt-parameter}, +\grammarterm{variable-tt-parameter}, or +\grammarterm{concept-tt-parameter} without the ellipsis. \end{itemize} @@ -2988,16 +3241,20 @@ replacing each pack expansion parameter with its $i^\text{th}$ element. Such an element, in the context of the instantiation, is interpreted as follows: + \begin{itemize} \item if the pack is a template parameter pack, the element is -an \grammarterm{id-expression} -(for a constant template parameter pack), -a \grammarterm{typedef-name} -(for a type template parameter pack declared without \tcode{template}), or -a \grammarterm{template-name} -(for a type template parameter pack declared with \tcode{template}), -designating the $i^\text{th}$ corresponding type or value template argument; +\begin{itemize} +\item +an \grammarterm{id-expression} for a constant template parameter pack, +\item +a \grammarterm{typedef-name} for a type template parameter pack, or +\item +a \grammarterm{template-name} for a template template parameter pack +\end{itemize} +designating the $i^\text{th}$ corresponding +type, template, or constant template argument; \item if the pack is a function parameter pack, the element is an @@ -3949,8 +4206,10 @@ \item if they declare constant template parameters, they have equivalent types ignoring the use of \grammarterm{type-constraint}{s} for placeholder types, and -\item if they declare template template parameters, their template -parameters are equivalent. +\item if they declare template template parameters, +%FIXME: What are "their kinds"? And what does it mean for kinds to be the same? +%FIXME: We refer to "kinds" in [temp.param]/p2 but never define it. +their kinds are the same and their \grammarterm{template-head}{s} are equivalent. \end{itemize} When determining whether types or \grammarterm{type-constraint}{s} are equivalent, the rules above are used to compare expressions @@ -4046,16 +4305,30 @@ the more constrained template (if one exists) as determined below. \pnum -To produce the transformed template, for each type, constant, or template +To produce the transformed template, for each +%FIXME: Don't we want to append "template parameter" to each of these? +%FIXME: As is, it reads as if it only applies to "conecpt". +%FIXME: E.g., we mean "type template parameter", not "type". +type, constant, +type template, variable template, or concept template parameter (including template parameter packs\iref{temp.variadic} -thereof) synthesize a unique type, value, or class template -respectively and substitute it for each occurrence of that parameter +thereof) synthesize a unique type, value, class template, +variable template, or concept, +respectively, and substitute it for each occurrence of that parameter in the function type of the template. \begin{note} The type replacing the placeholder in the type of the value synthesized for a constant template parameter is also a unique synthesized type. \end{note} + +\pnum +%FIXME: What's a "synthesized template"? Do we mean the synthesized +%FIXME: template described above? If so, say so. +A synthesized template has the same \grammarterm{template-head} as +its corresponding template template parameter. + +\pnum Each function template $M$ that is a member function is considered to have a new first parameter of type $X(M)$, described below, @@ -4773,7 +5046,7 @@ as a \grammarterm{template-name} or a \grammarterm{type-name}. When it is used with a \grammarterm{template-argument-list}, -as a \grammarterm{template-argument} for a template template parameter, +as a \grammarterm{template-argument} for a type template template parameter, or as the final identifier in the \grammarterm{elaborated-type-specifier} of a friend class template declaration, it is a \grammarterm{template-name} that refers to the @@ -5047,11 +5320,9 @@ A template argument that is equivalent to a template parameter can be used in place of that template parameter in a reference to the current instantiation. -For a template \grammarterm{type-parameter}, -a template argument is equivalent to a template parameter +A template argument is equivalent to a type template parameter if it denotes the same type. -For a constant template parameter, -a template argument is equivalent to a template parameter +A template argument is equivalent to a constant template parameter if it is an \grammarterm{identifier} that names a variable that is equivalent to the template parameter. A variable is equivalent to a template parameter if @@ -5295,8 +5566,7 @@ \item denoted by a \grammarterm{simple-template-id} in which either the template name is a template parameter or any of the -template arguments is a dependent type or an expression that is type-dependent -or value-dependent or is a pack expansion, +template arguments is dependent\iref{temp.dep.temp}, \begin{footnote} This includes an injected-class-name\iref{class.pre} of a class template used without a \grammarterm{template-argument-list}. @@ -5492,7 +5762,9 @@ is value-dependent if \begin{itemize} \item -it is a concept-id and any of its arguments are dependent, +it is a concept-id and +its \grammarterm{concept-name} is dependent or +any of its arguments are dependent\iref{temp.dep.temp}, \item it is type-dependent, \item @@ -5600,6 +5872,10 @@ designates or points to a member of the current instantiation or a member of a dependent type. +\pnum +%FIXME: "also" adds nothing here and reads like a note; remove it? +A template argument is also dependent if it is a pack expansion. + \pnum A template template parameter is dependent if it names a template parameter or @@ -8585,10 +8861,12 @@ \end{example} \pnum -A template type argument +A type template argument \tcode{T}, a template template argument -\tcode{TT}, +\tcode{TT} denoting a class template or an alias template, +a template template argument +\tcode{VV} denoting a variable template or a concept, or a constant template argument \tcode{i} can be deduced if @@ -8607,6 +8885,7 @@ @\opt{TT}@ @\opt{TT}@ @\opt{TT}@ +@\opt{TT}@ @\opt{TT}@<> \end{codeblock} where @@ -8641,22 +8920,18 @@ \end{note} Similarly, -\tcode{} -represents template argument lists where at least one argument contains a -\tcode{T}, -\tcode{} -represents template argument lists where at least one argument contains an -\tcode{i} +\tcode{<$X$>} represents template argument lists where +at least one argument contains an $X$, where +$X$ is one of \tcode{T}, \tcode{i}, \tcode{TT}, or \tcode{VV}; and \tcode{<>} represents template argument lists where no argument contains a -\tcode{T} -or an -\tcode{i}. +\tcode{T}, an \tcode{i}, a \tcode{TT}, or a \tcode{VV}. \pnum -If \tcode{P} has a form that contains \tcode{} -or \tcode{}, then each argument $\mathtt{P}_i$ of the +If \tcode{P} has a form that contains +\tcode{}, \tcode{}, \tcode{}, or \tcode{}, +then each argument $\mathtt{P}_i$ of the respective template argument list of \tcode{P} is compared with the corresponding argument $\mathtt{A}_i$ of the corresponding template argument list of \tcode{A}. If the template argument list From a98882212e0367ab0a13545c45bd910cb11d9c0c Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Sun, 23 Feb 2025 21:34:46 -0800 Subject: [PATCH 2/4] [temp.constr.concept] Replace "The constraint" with CD to clarify. --- source/templates.tex | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/templates.tex b/source/templates.tex index b34b37e515..423823bb49 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -1841,8 +1841,7 @@ the parameter mapping of \tcode{CD} and the arguments of \tcode{CI}. \pnum -%FIXME: What "constraint"? CD? -The constraint is satisfied if \tcode{CI$''$} is satisfied. +\tcode{CD} is satisfied if \tcode{CI$''$} is satisfied. \begin{note} Checking whether \tcode{CI$''$} is satisfied can lead to further normalization of concept-dependent constraints. From da036860d62da2aaffa27f088518b568b005a7bd Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Sun, 23 Feb 2025 22:41:18 -0800 Subject: [PATCH 3/4] [temp.constr.concept] Turn "satisfied" into a definition. --- source/templates.tex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/templates.tex b/source/templates.tex index 423823bb49..5ee68f4a02 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -1818,7 +1818,8 @@ \grammarterm{concept-name} names a dependent concept named \tcode{C}. \pnum -To determine if \tcode{CD} is satisfied, +To determine if \tcode{CD} is +\defnx{satisfied}{constraint!satisfaction!concept-dependent}, the parameter mapping and template arguments are first substituted into \tcode{C}. If substitution results in an invalid concept-id in From 17499575f99ae5a5270e052bc9d72e416c056a77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20K=C3=B6ppe?= Date: Sat, 15 Mar 2025 00:24:39 +0000 Subject: [PATCH 4/4] [temp.param] Remove mistaken "opt". This fixes an oversight in the paper. --- source/templates.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/templates.tex b/source/templates.tex index 5ee68f4a02..0294586daa 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -266,7 +266,7 @@ \begin{bnf} \nontermdef{type-tt-parameter}\br template-head type-parameter-key \opt{\terminal{...}} \opt{identifier}\br - template-head type-parameter-key \opt{identifier} \opt{type-tt-parameter-default} + template-head type-parameter-key \opt{identifier} type-tt-parameter-default \end{bnf} \begin{bnf}