diff --git a/src/constraints.tex b/src/constraints.tex index 7b01213..fe1dd82 100644 --- a/src/constraints.tex +++ b/src/constraints.tex @@ -54,13 +54,11 @@ \enternote The satisfaction of constraints on class templates, alias templates, and variable templates is required when referring to a template specialization -(\ref{temp.names}). The satisfaction of constraints on functions and +(\ref{temp.names}). +% +The satisfaction of constraints on functions and function templates is required during overload resolution -(\ref{over.match.viable}). The satisfaction of constraints introduced by -\grammarterm{constrained-type-specifier}{s} (\ref{dcl.spec.auto.constr}) -in the type of a variable or declared return type of a function is -required when values are deduced for their corresponding placeholders -(\ref{dcl.spec.auto}). +(\ref{over.match.viable}). \exitnote % Determining if a constraint is satisfied entails the substitution @@ -199,10 +197,7 @@ \enternote A predicate constraint is introduced by the \grammarterm{constraint-expression} of a -\grammarterm{requires-clause} (\ref{temp.constr.decl}), -or as the associated constraint of a -\grammarterm{constrained-parameter} (\ref{temp.param}) or -\grammarterm{template-introduction} (\ref{temp.intro}). +\grammarterm{requires-clause} (\ref{temp.constr.decl}). \exitnote % After substitution, \tcode{E} shall have type \tcode{bool}. @@ -556,11 +551,8 @@ \pnum Constraints can also be associated with a declaration through the use of -\grammarterm{template-introduction}{}s, \grammarterm{constrained-parameter}{}s in a -\grammarterm{template-parameter-list}, and -\grammarterm{constrained-type-specifier}{}s in the parameter-type-list -of a function template. +\grammarterm{template-parameter-list}. % Each of these forms introduces additional \grammarterm{constraint-expression}{s} that are used to constrain the declaration. @@ -678,32 +670,13 @@ % First, create a new expression \tcode{E} by replacing all subexpressions in \tcode{X} that refer to concepts with their -corresponding definitions. In particular, -% -\begin{xaddedblock} +corresponding definitions. That is, replace all \grammarterm{id-expression}{s} of the form \tcode{C}, where \tcode{C} is a concept with the result of substituting the template arguments \tcode{A$1$, A$2$, ..., A$N$} into the \grammarterm{constraint-expression} of \tcode{C}. -\end{xaddedblock} -% -\begin{xremovedblock} -\begin{itemize} -\item replace all function calls of the form -\tcode{C()}, where \tcode{C} refers to the function -concept \tcode{D} (\ref{dcl.spec.concept}) selected by the rules for concept -resolution (\ref{temp.constr.resolve}), with the result of substituting -\tcode{A$1$, A$2$, ..., A$N$} into the expression returned by \tcode{D}, and - -\item replace all \grammarterm{id-expression}{s} of the form -\tcode{C}, where \tcode{C} is the variable -concept \tcode{D} (\ref{dcl.spec.concept}) selected by the rules for concept -resolution (\ref{temp.constr.resolve}), with the result of substituting -\tcode{A$1$, A$2$, ..., A$N$} into the initializer of \tcode{D}. -\end{itemize} -\end{xremovedblock} % -If \xremoved{any such} \xadded{that} substitution fails, the program is ill-formed. +If that substitution fails, the program is ill-formed. % Second, transform the expression \tcode{E} into a constraint as follows: \begin{itemize} @@ -756,10 +729,10 @@ % \enterexample \begin{codeblock} -template concept bool C1() { return sizeof(T) == 1; } -template concept bool C2 = C1() && 1 == 2; -template concept bool C3 = requires { typename T::type; }; -template concept bool C4 = requires (T x) { ++x; } +template concept C = sizeof(T) == 1; +template concept C2 = C1() && 1 == 2; +template concept C3 = requires { typename T::type; }; +template concept C4 = requires (T x) { ++x; } template void f1(T); // \#1 template void f2(T); // \#2 @@ -915,132 +888,3 @@ \end{addedblock} \end{quote} - -%% -%% Resolution of qualified references to concepts -%% -\rSec2[temp.constr.resolve]{Resolution of qualified references to concepts} - -Remove this section. Concept definitions can no longer overload. - -\begin{quote} -\begin{xremovedblock} -\pnum -\defn{Concept resolution} is the process of selecting a concept -from a set of concept definitions referred to by a -\grammarterm{qualified-concept-name}, -% -or from a set of declarations including one or more concept definitions -referred to by a \grammarterm{simple-template-id} or a \grammarterm{qualified-id} -whose \grammarterm{unqualified-id} is a \grammarterm{simple-template-id}. -% -Concept resolution is performed when such a name appears -\begin{itemize} -\item as a \grammarterm{constrained-type-specifier} (\ref{dcl.spec.auto.constr}), -\item in a \grammarterm{constrained-parameter} (\ref{temp.param}), -\item in a \grammarterm{template-introduction} (\ref{temp.intro}), or -\item within a \grammarterm{constraint-expression} (\ref{temp.constr.decl}). -\end{itemize} -Within such a name, let \tcode{C} be the \grammarterm{concept-name} or -\grammarterm{template-name} that refers to the set of concept definitions. - -\pnum -The selection of a concept from this set is done by matching the -template parameters of each concept in that set to a sequence of template -arguments and \defn{wildcard}{s}. -% -This sequence is called the \defn{concept argument list}, and its elements -are called \defn{concept argument}{s}. -% -For the purpose this matching, a wildcard can match a template -parameter of any kind (type, non-type, template) as described below. - -\pnum -The method for determining the concept argument list depends on the -context in which \tcode{C} appears. -% -\begin{itemize} -\item If \tcode{C} is part of a \grammarterm{constrained-type-specifier} or -\grammarterm{constrained-parameter}, -then - \begin{itemize} - \item if \tcode{C} is a \grammarterm{constrained-type-name}, the concept - argument list is comprised of a single wildcard, or - \item if \tcode{C} is the \grammarterm{concept-name} of a - \grammarterm{partial-concept-id}, the concept argument list is comprised of a - single wildcard followed by the \grammarterm{template-argument}{s} of that - \grammarterm{partial-concept-id}. - \end{itemize} - -\item If \tcode{C} is the \grammarterm{concept-name} in a -\grammarterm{template-introduction}. the concept argument list is a sequence -of wildcards of the same length as the \grammarterm{introduction-list} of -the \grammarterm{template-introduction}. - -\item If \tcode{C} appears as a \grammarterm{template-name} of a -\grammarterm{simple-template-id}, the concept argument list is the sequence of -\grammarterm{template-argument}{s} of that \grammarterm{simple-template-id}. -\end{itemize} - -\pnum -The selection of a concept from the set referred to by \tcode{C} is done -by matching the concept argument list against the template parameter lists of -each concept in that set. -% -For a concept \tcode{CC} in that set to be a viable selection, each -argument in the concept argument list is matched against the corresponding -template parameters of \tcode{CC}. -% -Default template arguments of \tcode{CC} (if any) are instantiated for each -template parameter that does not correspond to a concept argument. Instantiated -default arguments are appended to the concept argument list. -% -If the last declared template parameter of \tcode{CC} is not a parameter pack -and the number of template parameters of \tcode{CC} is greater than the -number of concept arguments, \tcode{CC} is not a viable selection. -% -Otherwise, concept arguments are matched to template parameters using the -following rules: -% -\begin{itemize} -\item a template argument matches a template parameter if and only if -it matches in kind (type, non-type, template) and type according to the -rules in \ref{temp.arg}; - -\item a wildcard matches a template parameter of any kind; - -\item a template parameter pack (\cxxref{temp.variadic}), matches zero or more -concept arguments, provided that each of those arguments matches the pattern -of the template parameter pack using the rules above for matching matching -concept arguments and template parameters. -\end{itemize} -% -If any concept arguments do not match a corresponding template parameter, -the concept \tcode{CC} is not a viable selection. -% -The concept selected by concept resolution shall be the single viable selection -in the set of concepts referred by \tcode{C}. -% -\enterexample -\begin{codeblock} -template concept bool C1() { return true; } // \#1 -template concept bool C1() { return true; } // \#2 -template concept bool C2() { return true; } -template concept bool C2() { return true; } -template concept bool C3 = true; - -void f1(const C1*); // OK: \tcode{C1} selects \#1 -void f2(C1); // OK: \tcode{C1} selects \#2 - -template T> struct S1; // error: no matching concept for \tcode{C2<0>}, - // mismatched template arguments -template struct S2; // error: resolution of \tcode{C2} is ambiguous, - // both concepts are viable - -C3{...Ts} void q1(); // OK: selects \tcode{C3} -C3{T} void q2(); // OK: selects \tcode{C3} -\end{codeblock} -\exitexample - -\end{xremovedblock} -\end{quote} diff --git a/src/declarations.tex b/src/declarations.tex index 86b0a95..605213b 100644 --- a/src/declarations.tex +++ b/src/declarations.tex @@ -30,992 +30,7 @@ \setcounter{Paras}{12} \begin{quote} \pnum -A \grammarterm{concept-definition} shall only appear as a part of -\grammarterm{template-declaration}. +A \grammarterm{concept-definition} (\ref{temp.concept}) shall only appear as +part of \grammarterm{template-declaration}. \end{quote} -%% -%% Specifiers -%% -\rSec1[dcl.spec]{Specifiers} - -Remove this introduction. - -\begin{xremovedblock} -Extend the \grammarterm{decl-specifier} production -in paragraph 1 to include the \tcode{concept} specifier. - -\begin{quote} -\pnum -The specifiers that can be used in a declaration are - -\begin{bnf} -\nontermdef{decl-specifier}\br - storage-class-specifier\br - defining-type-specifier\br - function-specifier\br - \terminal{friend}\br - \terminal{typedef}\br - \terminal{constexpr}\br - \terminal{concept} -\end{bnf} -\end{quote} -\end{xremovedblock} - -%% -%% Type specifiers -%% -\setcounter{subsection}{6} -\rSec2[dcl.type]{Type specifiers} - - -%% -%% Simple type specifiers -%% -\setcounter{subsubsection}{1} -\rSec3[dcl.type.simple]{Simple type specifiers} - -Add \grammarterm{constrained-type-specifier} -to the grammar for \grammarterm{simple-type-specifier}{}s. - -\begin{quote} -\begin{bnf} -\nontermdef{simple-type-specifier}\br - nested-name-specifier\opt type-name\br - nested-name-specifier \terminal{template} simple-template-id\br - nested-name-specifier\opt template-name\br - \terminal{char}\br - \terminal{char16_t}\br - \terminal{char32_t}\br - \terminal{wchar_t}\br - \terminal{bool}\br - \terminal{short}\br - \terminal{int}\br - \terminal{long}\br - \terminal{signed}\br - \terminal{unsigned}\br - \terminal{float}\br - \terminal{double}\br - \terminal{void}\br - \terminal{auto}\br - decltype-specifier\br - \added{constrained-type-specifier} -\end{bnf} -\end{quote} - -Modify paragraph 2 to begin: - -\begin{quote} -\setcounter{Paras}{1} -\pnum -\removed{The \grammarterm{simple-type-specifier} \tcode{auto} specifier is a -placeholder for a type to be deduced (\ref{dcl.spec.auto}).} -\added{The \grammarterm{simple-type-specifier} \tcode{auto} and -\grammarterm{constrained-type-specifier}{s} -are placeholders for values (type, non-type, template) to be deduced -(\ref{dcl.spec.auto}).} -\end{quote} - -Add \grammarterm{constrained-type-specifier}{s} to the table of -\grammarterm{simple-type-specifier}{s} in Table~\ref{tab:simple.type.specifiers}. - -\renewcommand{\thetable}{\arabic{table}} -\setcounter{table}{10} -\begin{simpletypetable} -{\grammarterm{simple-type-specifier}{s} and the types they specify} -{tab:simple.type.specifiers} -{ll} -\topline -Specifier(s) & Type \\ \capsep -\grammarterm{type-name} & the type named \\ -\grammarterm{simple-template-id} & the type as defined in~\ref{temp.names} \\ -\multicolumn{2}{|c|}{\vdots} \\ -\tcode{auto} & placeholder for a type to be deduced \\ -\tcode{decltype(auto)} & placeholder for a type to be deduced \\ -\tcode{decltype(}\grammarterm{expression}\tcode{)} & the type as defined below \\ -\added{\grammarterm{constrained-type-specifier}} & \added{placeholder for value (type, non-type, template) to be deduced} \\ -\end{simpletypetable} - - -%% -%% Auto specifier -%% -\setcounter{subsubsection}{3} -\rSec3[dcl.spec.auto]{\tcode{auto} specifier} - -Extend this section to allow for \grammarterm{constrained-type-specifier}{s} -as a new syntax for designating placeholders. The meaning of -\grammarterm{constrained-type-specifier}{s} is described in -\ref{dcl.spec.auto.constr}. - -Replace paragraph 1 with the text below. - -\begin{quote} -\begin{removedblock} -\pnum -The \tcode{auto} and \tcode{decltype(auto)} \grammarterm{type-specifier}{s} -are used to -designate a placeholder type that will be replaced later by deduction -from an initializer. The \tcode{auto} -\grammarterm{type-specifier} is also used to -introduce a function type having a \grammarterm{trailing-return-type} or to -signify that a lambda is a generic lambda (\cxxref{expr.prim.lambda.closure}). -The \tcode{auto} \grammarterm{type-specifier} is also used to introduce a -structured binding declaration (\cxxref{dcl.struct.bind}). -\end{removedblock} -\begin{addedblock} -The \grammarterm{type-specifier}{}s \tcode{auto} and \tcode{decltype(auto)} -and \grammarterm{constrained-type-specifier}{}s designate a placeholder -(type, non-type, or template) that will be replaced later, either through -deduction or an explicit specification. -% -The \tcode{auto} and \tcode{decltype(auto)} \grammarterm{type-specifier}{}s -designate placeholder types; a \grammarterm{constrained-type-specifier} can -also designate placeholders for values and templates. -% -\enternote -The deduction of placeholders is done through the invention of template -parameters as described in \ref{dcl.spec.auto.deduct} and \ref{dcl.fct}. -\exitnote -% -Placeholders are also used to signify that a lambda is a generic lambda -(\ref{expr.prim.lambda}), that a function declaration is an -abbreviated function template (\ref{dcl.fct}), or that a -\grammarterm{trailing-return-type} in a \grammarterm{compound-requirement} -(\ref{expr.prim.req.compound}) introduces an argument deduction constraint -(\ref{temp.constr.deduct}). -% -The \tcode{auto} \grammarterm{type-specifier} is also introduce a function type -having a \grammarterm{trailing-return-type} or to introduce a structured binding -declaration \cxxref{dcl.struct.bind}. -% -\enternote -A \grammarterm{nested-name-specifier} can also include placeholders (\ref{expr.prim}). -Replacements for those placeholders are determined according to the rules -in this section. -\exitnote -% -\end{addedblock} -\end{quote} - -Modify paragraph 2 to allow \grammarterm{constrained-type-specifier}{}s -with function declarators, except in the declared return type. - -\begin{quote} -\pnum -\removed{The placeholder type}\added{Placeholders} can appear with a function -declarator in the \grammarterm{decl-specifier-seq}, \grammarterm{type-specifier-seq}, -\grammarterm{conversion-function-id}, or \grammarterm{trailing-return-type}, -in any context where such a declarator is valid. -% -If the function declarator includes a \grammarterm{trailing-return-type} -(\ref{dcl.fct}), that \grammarterm{trailing-return-type} specifies the declared -return type of the function. Otherwise, the function declarator shall declare -a function. -% -If the declared return type of the function contains a placeholder, the -return type of the function is deduced from non-discarded return statements, -if any, in the body of the function (\ref{stmt.if}). -% -\added{ -In a function declarator of the form \tcode{auto D -> T} where -\tcode{T} contains placeholders, the initial \tcode{auto} does -not designate a placeholder. -} -\end{quote} - - -Modify paragraph 3 to allow the use of \tcode{auto} within the -parameter type of a lambda or function. - -\begin{quote} -\pnum -If \removed{the \tcode{auto} \grammarterm{type-specifier}} \added{a placeholder} -appears \removed{as one of the \grammarterm{decl-specifier}{}s in the -\grammarterm{decl-specifier-seq} of a \grammarterm{parameter-declaration}} -\added{in a parameter type} of a \grammarterm{lambda-expression}, the lambda -is a generic lambda -(\ref{expr.prim.lambda}). -% -\enterexample -\begin{codeblock} -auto glambda = [](int i, auto a) { return i; }; // OK: a generic lambda -\end{codeblock} -\exitexample -% -\begin{addedblock} -Similarly, if a placeholder appears in a parameter type of a function -declaration, the function declaration declares an abbreviated function -template (\ref{dcl.fct}). -% -\enterexample -\begin{codeblock} -void f(const auto&, int); // OK: an abbreviated function template -\end{codeblock} -\exitexample -\end{addedblock} -\end{quote} - - -Add the following after paragraph 3 to describe when -\grammarterm{constrained-type-specifier}{}s in the return type -refer to template parameters. - -\begin{quote} -\begin{addedblock} -\pnum -A \grammarterm{constrained-type-specifier} \tcode{C1} within the declared -return type of an abbreviated function template declaration does not -designate a placeholder if its introduced -\grammarterm{constraint-expression} (\ref{dcl.spec.auto.constr}) -is determined to be equivalent, using the rules in \ref{temp.over.link} -for comparing expressions, to the introduced -\grammarterm{constraint-expression} for a -\grammarterm{constrained-type-specifier} \tcode{C2} in the -\grammarterm{parameter-declaration-clause} of that function declaration. -% -Instead, \tcode{C1} is replaced by the template parameter invented for -\tcode{C2} (\ref{dcl.fct}). -\enterexample -\begin{codeblock} -template concept bool C = true; - -template struct Tuple; - -C const& f1(C); // has one template parameter and no deduced return type -Tuple f2(C); // has one template parameter and a deduced return type -\end{codeblock} -In the declaration \tcode{f1}, the \grammarterm{constraint-expression} -introduced by the \grammarterm{constrained-type-specifier}{}s in the -\grammarterm{parameter-declaration-clause} and return type are equivalent -; they would both introduce the expression \tcode{C}, for some invented -template parameter \tcode{T}. -% -In \tcode{f2}, the use of \tcode{C} in the return type would introduce the -\grammarterm{constraint-expression} \tcode{(C \&\& ...)}, which is -distinct from the \grammarterm{constraint-expression} \tcode{C} introduced -by the invented \grammarterm{constrained-parameter} (\ref{temp.param}) for -the \grammarterm{constrained-type-specifier} in the -\grammarterm{parameter-declaration-clause} according to the rules in -\ref{dcl.fct}. -\exitexample -\end{addedblock} -\end{quote} - - -Add the following after paragraph 4 to allow the use of \tcode{auto} in the -\grammarterm{trailing-return-type} of a \grammarterm{compound-requirement}. -Also, disallow the use of \tcode{decltype(auto)} with function parameters -and deduction constraints. - -\begin{quote} -\begin{addedblock} -\pnum -If a placeholder appears in the \grammarterm{trailing-return-type} -of a \grammarterm{compound-requirement} in a \grammarterm{requires-expression} -(\ref{expr.prim.req.compound}), that return type introduces an argument -deduction constraint (\ref{temp.constr.deduct}). -% -\enterexample -\begin{codeblock} -template concept C = - requires (T i) { - {*i} -> const auto&; // OK: introduces an argument deduction constraint - }; -} -\end{codeblock} -\exitexample - -\pnum -The \tcode{decltype(auto)} \grammarterm{type-specifier} shall not appear -in the declared type of a \grammarterm{parameter-declaration} or the -\grammarterm{trailing-return-type} of a \grammarterm{compound-requirement}. -\end{addedblock} -\end{quote} - - -Modify paragraph 4 in the \Cpp Standard (paragraph 7, here) to allow multiple -placeholders within a variable declaration. - -\begin{quote} -\pnum -The type of a variable declared using -\added{a placeholder} -\removed{\tcode{auto} or \tcode{decltype(auto)}} -is deduced from its initializer. -% -This use is allowed in an initializing declaration (\cxxref{11.6}) of a variable. -% -\removed{\tcode{auto} or \tcode{decltype(auto)} shall appear as one -of the \grammarterm{decl-specifier}{}s in the \grammarterm{decl-specifier-seq} } -% -\added{ -A placeholder can appear anywhere in the declared type of the variable, but -\tcode{decltype(auto)} shall appear only as one of the -\grammarterm{decl-specifier}{}s of the \grammarterm{decl-specifier-seq}. -} -\removed{and the}\added{The} \grammarterm{decl-specifier-seq} \added{of such a -variable} shall be followed by one or more \grammarterm{init-declarator}{}s, -each of which shall be followed by a non-empty initializer. -% -In an initializer of the form -\begin{codeblock} -( expression-list ) -\end{codeblock} -the \grammarterm{expression-list} shall be a single -\grammarterm{assignment-expression}. -% -\enterexample -\begin{codeblock} -auto x = 5; // OK: \tcode{x} has type int -const auto *v = &x, u = 6; // OK: \tcode{v} has type \tcode{const int*}, \tcode{u} has type \tcode{const int} -static auto y = 0.0; // OK: \tcode{y} has type \tcode{double} -auto int r; // error: \tcode{auto} is not a storage-class-specifier -auto f() -> int; // OK: \tcode{f} returns \tcode{int} -auto g() { return 0.0; } // OK: \tcode{g} returns \tcode{double} -auto h(); // OK: \tcode{h}'s return type will be deduced when it is defined -\end{codeblock} -\exitexample -\end{quote} - -Add the following declarations to the example in the previous paragraph. - -\begin{quote} -\begin{addedblock} -\begin{codeblock} -struct N { - template struct Wrap; - template static Wrap make_wrap(T); -}; -template struct Pair; -template Pair make_pair(T, U); -template struct Size { void f(int) { } }; - -void (auto::* p1)(auto) = &Size<0>::f; // OK: \tcode{p1} has type \tcode{void(Size<0>::*)(int)} -Pair p2 = make_pair(0, 'a'); // OK: \tcode{p2} has type \tcode{Pair} -N::Wrap a = N::make_wrap(0.0); // OK: \tcode{a} has type \tcode{Wrap} -auto::Wrap x = N::make_wrap(0); // error: failed to deduce value for \tcode{auto} -Size y = Size<0>{}; // error: failed to deduce value for \tcode{auto} - -template concept bool C = true; -template concept bool D = false; -C z1 = 0; // OK: \tcode{z1} has type \tcode{int} -D z2 = 0; // error: constraints not satisfied -C cf1() { return 0.0; }; // OK: \tcode{cf1} returns \tcode{double} -D cf2() { return 0.0; }; // error: constraints not satisfied -auto cf3() -> C; // OK: \tcode{cf3}'s return type will be deduced when it is defined -\end{codeblock} -\end{addedblock} -\end{quote} - -Update paragraph 6 in the \Cpp Standard (paragraph 8, here) to disallow -placeholders in other contexts. - -\begin{quote} -\pnum -A program that uses \removed{\tcode{auto} or \tcode{decltype(auto)}} -\added{placeholders} in a context not explicitly allowed in this section is -ill-formed. -\end{quote} - - -Modify paragraph 7 in the \Cpp standard (paragraph 9, here) to read: - -\begin{quote} -\pnum -If the \grammarterm{init-declarator-list} contains more than one -\grammarterm{init-declarator}, they shall all form declarations of variables. -The type of each declared variable is determined is determined by placeholder -type deduction (\ref{dcl.spec.auto.deduct}), and if -the type that replaces \removed{the placeholder type} -\added{the declared variable type or return type} -is not the same in each deduction, the program is ill-formed. -\end{quote} - -Add add the following examples to that paragraph. - -\begin{quote} -\enterexample -\begin{addedblock} -\begin{codeblock} -Pair p1 = make_pair(0, 0), - *p2 = &p1; // OK: replacement type is \tcode{Pair} -Pair p3 = make_pair(0, 'a'), - p4 = make_pair('a', 0); // error: different replacement types -\end{codeblock} -\end{addedblock} -\exitexample -\end{quote} - -Modify paragraph 8 in the \Cpp Standard (paragraph 10, here) to read: -\begin{quote} -\pnum -If a function with a declared return type that contains -\removed{a placeholder type} -\added{placeholders} -has multiple non-discarded \tcode{return} statements, -the return type is deduced for each such \tcode{return} statement. -If the type deduced is not the same in each deduction, -the program is ill-formed. -\end{quote} - -Modify paragraph 9 in \Cpp Standard (paragraph 11, here) to read: - -\begin{quote} -\pnum -If a function with a declared return type that uses -\removed{a placeholder type} -\added{placeholders} -has no non-discarded \tcode{return} statements, the return type is deduced as -though from a \tcode{return} statement with no operand at the closing brace of -the function body. -\end{quote} - -Modify the first sentence of paragraph 10 in the \Cpp Standard (paragraph 12, -here). - -\begin{quote} -\pnum -If the type of an entity with an undeduced placeholder \removed{type} -is needed to determine the type of an expression, the program is -ill-formed. -\end{quote} - -Modify paragraph 12 in the \Cpp Standard (paragraph 14, here) to read: - -\begin{quote} -\setcounter{Paras}{13} -\pnum -Redeclarations or specializations of a function or function template -with a declared return type that uses -\removed{a placeholder type} -\added{placeholders} shall also use that placeholder, -not a deduced type. -% -\added{If a placeholder is designated by a -\grammarterm{constrained-type-specifier}, redeclarations or specializations -shall use the same \grammarterm{constrained-type-specifier}.} -\end{quote} - -Add the following examples to that paragraph. - -\begin{quote} -\begin{addedblock} -\begin{codeblock} -template concept bool C1 = true; -template concept bool C2 = true; - -template auto cf(T) -> C1; // \#1 -template C1 cf(T); // \#2, redeclaration of \#1 -template C2 cf(T); // error: redeclared with different placeholder -\end{codeblock} -\end{addedblock} -\end{quote} - -Modify paragraph 13 in the \Cpp Standard (paragraph 15, here) to disallow -placeholders in the return types of virtual functions. - -\begin{quote} -\pnum -A function declared with a return type that uses -\removed{a placeholder type} -\added{placeholders} -shall not be virtual (\cxxref{class.virtual}). -\end{quote} - - -Modify paragraph 14 in the \Cpp Standard (paragraph 16, here) to read: - -\begin{quote} -\pnum -An explicit instantiation declaration (\ref{temp.explicit}) does not cause the -instantiation of an entity declared using -\removed{a placeholder type} -\added{placeholders}, -but it also does not prevent that entity from being instantiated as needed to -determine its type. -\end{quote} - - -%%% -%%% Placeholder type deduction -%%% -\rSec4[dcl.spec.auto.deduct]{Placeholder type deduction} - - -\begin{quote} -\pnum -\defn{Placeholder type deduction} is the process by which a type containing -\removed{a placeholder type} \added{placeholders} is replaced by -\removed{a deduced type} \added{deduced values (type, non-type, template)}. - -\pnum -A type \tcode{T} containing a \removed{placeholder type}\added{placeholders}, -and a corresponding initializer \tcode{e}, -are determined as follows: - -\begin{itemize} -\item -for a non-discarded \tcode{return} statement that occurs -in a function declared with a return type -that contains \removed{a placeholder type}\added{placeholders}, -\tcode{T} is the declared return type -and \tcode{e} is the operand of the \tcode{return} statement. -If the \tcode{return} statement -has no operand, -then \tcode{e} is \tcode{void()}; -\item -for a variable declared with a type -that contains \removed{a placeholder type}\added{placeholders}, -\tcode{T} is the declared type of the variable -and \tcode{e} is the initializer. -If the initialization is direct-list-initialization, -the initializer shall be a \grammarterm{braced-init-list} -containing only a single \grammarterm{assignment-expression} -and \tcode{e} is the \grammarterm{assignment-expression}; -\item -for a non-type template parameter declared with a type -that contains \removed{a placeholder type}\added{placeholders}, -\tcode{T} is the declared type of the non-type template parameter -and \tcode{e} is the corresponding template argument. -\end{itemize} -% -In the case of a \tcode{return} statement with no operand -or with an operand of type \tcode{void}, -\tcode{T} shall be either -\tcode{decltype(auto)} \removed{or}\added{,} \cv{}~\tcode{auto}% -\added{, or a \grammarterm{constrained-type-specifier}}. - -% FIXME: This is a normative change. -% \added{Otherwise, if the initialization is copy-list-initialization, -% \tcode{T} shall be either \tcode{decltype(auto)}, \tcode{auto}, or a -% \grammarterm{constrained-type-specifier}.} - -\pnum -If the placeholder is the \tcode{auto} \grammarterm{type-specifier} -\added{or a \grammarterm{constrained-type-specifier}}, the deduced type -$\mathtt{T}'$ replacing \tcode{T} is determined using the rules for template -argument deduction. -% -\removed{Obtain \tcode{P} from -\tcode{T} by replacing the occurrences of \tcode{auto} with either a new -invented type template parameter \tcode{U} or, -if the initialization is copy-list-initialization, with -\tcode{std::initializer_list}.} -% -\begin{addedblock} -Otherwise, obtain a type \tcode{P} from \tcode{T} as follows: -\begin{itemize} -% FIXME: This doesn't do the right thing at all. -\item if the initialization is a copy-list-initialization -and a placeholder is a \grammarterm{decl-specifier} of the -\grammarterm{decl-specifier-seq} of the variable declaration, replace that -occurrence of the placeholder with \tcode{std::initializer_list} -where \tcode{U} is an invented type template parameter; - -\item otherwise, replace each occurrence of a placeholder in the -variable or return type with a new invented type template parameter -according to the rules for inventing template parameters -for placeholders in \ref{dcl.fct}. -\end{itemize} -\end{addedblock} -% -Deduce a value for \added{each} \removed{\tcode{U}} -\added{invented type template parameter} using the rules -of template argument deduction from a function -call~(\cxxref{temp.deduct.call}), -where \tcode{P} is a -function template parameter type and -the corresponding argument is \tcode{e}. -% -If the deduction fails, the declaration is ill-formed. -% -\added{If any placeholders in the declared type were introduced by a -\grammarterm{constrained-type-specifier}, then define \tcode{C} to be a -\grammarterm{constraint-expression} as follows:} -\begin{addedblock} -\begin{itemize} -\item if there is single \grammarterm{constrained-type-specifier}, -then \tcode{C} is the \grammarterm{constraint-expression} introduced -by the invented template \grammarterm{constrained-parameter} (\ref{temp.param}) -corresponding to that \grammarterm{constrained-type-specifier}; -\item otherwise, \tcode{C} is the \grammarterm{logical-and-expression} -(\cxxref{expr.log.and}) whose operands are the -\grammarterm{constraint-expression}{s} introduced by the invented -template \grammarterm{constrained-parameter}{s} corresponding to -each \grammarterm{constrained-type-specifier}, in order of appearance. -\end{itemize} -\end{addedblock} -% -\added{If the normalized constraint for \tcode{C} (\ref{temp.constr.decl}) -is not satisfied by the deduced values, the declaration is ill-formed.} -% -Otherwise, $\mathtt{T}'$ is obtained by -substituting the deduced \removed{\tcode{U}} -\added{values for the invented type template parameters} -into \tcode{P}. - -\enterexample -\begin{codeblock} -auto x1 = { 1, 2 }; // \tcode{decltype(x1)} is \tcode{std::initializer_list} -auto x2 = { 1, 2.0 }; // error: cannot deduce element type -auto x3{ 1, 2 }; // error: not a single element -auto x4 = { 3 }; // \tcode{decltype(x4)} is \tcode{std::initializer_list} -auto x5{ 3 }; // \tcode{decltype(x5)} is \tcode{int} -\end{codeblock} -\exitexample - -\enterexample -\begin{codeblock} -const auto &i = expr; -\end{codeblock} -The type of \tcode{i} is the deduced type of the parameter \tcode{u} in -the call \tcode{f(expr)} of the following invented function template: -\begin{codeblock} -template void f(const U& u); -\end{codeblock} -\exitexample -\end{quote} - -Add the following to the first example in paragraph 4. - -\begin{quote} -\begin{addedblock} -\enterexample -\begin{codeblock} -template struct Vec { }; -template Vec make_vec(std::initializer_list) { return Vec{}; } - -template struct Tuple { }; -template auto make_tup(Ts... args) { return Tuple{}; } - -auto& x3 = *x1.begin(); // OK: \tcode{decltype(x3)} is \tcode{int\&} -const auto* p = &x3; // OK: \tcode{decltype(p)} is \tcode{const int*} -Vec v1 = make_vec({1, 2, 3}); // OK: \tcode{decltype(v1)} is \tcode{Vec} -Vec v2 = {1, 2, 3}; // error: type deduction fails -Tuple v3 = make_tup(0, 'a'); // OK: \tcode{decltype(v3)} is \tcode{Tuple} -\end{codeblock} -\exitexample -\end{addedblock} -\end{quote} - - -Add the following after the second example in paragraph 4. - -\begin{quote} -\begin{addedblock} -\enterexample -\begin{codeblock} -template struct Pair; -template Pair make_pair(T, U); - -struct S { void mfn(bool); } s; -int fn(char, double); - -Pair p = make_pair(fn, &S::mfn); -\end{codeblock} -The declared type of \tcode{p} is the deduced type of the parameter -\tcode{x} in the call of \tcode{g(make_pair(fn, \&S::mfn))} of the following -invented function template: -\begin{codeblock} -template -void g(Pair< T1(*)(T2, T3), T4 (T5::*)(T6)> x); -\end{codeblock} -\exitexample - -\enterexample -\begin{codeblock} -template concept bool C = true; - -const C* cv = expr; -\end{codeblock} -The type of \tcode{cv} is deduced from the parameter \tcode{p1} in the -call \tcode{f1(expr)} of the following invented function: -\begin{codeblock} -template void f1(const T* p1); -\end{codeblock} -\exitexample - -\enterexample -\begin{codeblock} -auto cf(int) -> Pair { return expr; } -\end{codeblock} -The return type of \tcode{cf} is deduced from the parameter \tcode{p2} in the -call \tcode{f2(expr)} of the following invented function: -\begin{codeblock} -template void f2(Pair); -\end{codeblock} -Both \grammarterm{constrained-type-specifier}{}s in the return type of -\tcode{cf} correspond to the same invented template parameter. -\exitexample -\end{addedblock} -\end{quote} - - -%% -%% Constrained type specifiers -%% -\rSec4[dcl.spec.auto.constr]{Constrained type specifiers} - -Add this section to \ref{dcl.spec.auto}. - -\begin{quote} -\begin{addedblock} -\pnum -A \grammarterm{constrained-type-specifier} designates a placeholder -(type, non-type, or template) and introduces an associated constraint -(\ref{temp.constr.decl}). - -\begin{bnf} -\nontermdef{constrained-type-specifier}\br - qualified-concept-name - -\nontermdef{qualified-concept-name}\br - nested-name-specifier\opt constrained-type-name - -\nontermdef{constrained-type-name}\br - concept-name\br - partial-concept-id - -\xremoved{ -\nontermdef{concept-name}\br - identifier} - -\nontermdef{partial-concept-id}\br - concept-name \terminal{<} template-argument-list\opt \terminal{>} -\end{bnf} - -\enterexample -\begin{codeblock} -template concept C1 = false; -template concept C2 = false; -template class X> concept C3 = false; - -template class Array { }; -template class A> class Stack { }; -template class Alloc { }; - -void f1(C1); // \tcode{C1} designates a placeholder type -void f2(Array); // \tcode{C2} designates a placeholder for an integer value -void f3(Stack); // \tcode{C3} designates a placeholder for a class template -\end{codeblock} -\exitexample - -\begin{xremovedblock} -\pnum -An identifier is a \grammarterm{concept-name} if it refers to a set of -concept definitions (\ref{dcl.spec.concept}). -% -\enternote -The set of concepts has multiple members only when referring to a set of -overloaded function concepts. There is at most one member of this set when a -\grammarterm{concept-name} refers to a variable concept. -\exitnote -% -\enterexample -\begin{codeblock} -template concept bool C = true; // \#1 -template concept bool C = true; // \#2 -template concept bool D = true; // \#3 - -void f(C); // OK: the set of concepts referred to by C includes both \#1 and \#2; - // concept resolution (\ref{temp.constr.resolve}) selects \#1. -void g(D); // OK: the concept-name \tcode{D} refers only to \#3 -\end{codeblock} -\exitexample -\end{xremovedblock} - -\pnum -A \grammarterm{partial-concept-id} is a \grammarterm{concept-name} followed -by a sequence of \grammarterm{template-argument}{}s. - -\enterexample -\begin{codeblock} -template concept bool Seq = true; - -void f1(Seq<3>); // OK -void f2(Seq<>); // OK -\end{codeblock} -\exitexample - -\pnum -\xremoved{The concept designated by a \grammarterm{constrained-type-specifier} -is the one selected according to the rules for concept resolution in -\ref{temp.constr.resolve}.} - -\pnum -\enternote -The \grammarterm{constraint-expression} introduced by a -\grammarterm{constrained-type-name} is the one introduced by the invention of a -\grammarterm{constrained-parameter} (\ref{temp.param}). -% -The rules for inventing template parameters corresponding to placeholders -in the type of a variable or the declared return type of a function are -described in \ref{dcl.spec.auto.deduct}. -% -The rules for inventing template parameters corresponding to placeholders -in the \grammarterm{parameter-declaration-clause} of a -\grammarterm{lambda-expression} (\ref{expr.prim.lambda}) -or function declaration (\ref{dcl.fct}) are described in -\ref{dcl.fct}. -% -The rules for inventing a template parameter corresponding to placeholders -in the \grammarterm{trailing-return-type} of a -\grammarterm{compound-requirement} are described in -\ref{temp.constr.deduct}. -\exitnote - -\end{addedblock} -\end{quote} - - -%% -%% concept specifier -%% -\rSec2[dcl.spec.concept]{\tcode{concept} specifier} - -Remove this section. - -\begin{quote} -\begin{xremovedblock} -Add this section to \ref{dcl.spec}. - -\begin{quote} -\pnum -The \tcode{concept} specifier shall be applied only to the -definition of a function template or variable template, declared -in namespace scope (\cxxref{basic.scope.namespace}). -% -A function template definition having the \tcode{concept} -specifier is called a \defn{function concept}. -% -A function concept shall have no \grammarterm{exception-specification} -and is treated as if it were specified with \tcode{noexcept(true)} -(\cxxref{except.spec}). -% -When a function template is declared to be a concept, it shall be the only -declaration of that function template in the translation unit. -% -A variable template definition having the \tcode{concept} -specifier is called a \defn{variable concept}. -% -A \defn{concept definition} refers to either a function concept -and its definition or a variable concept and its initializer. -% -\enterexample -\begin{codeblock} -template - concept bool F1() { return true; } // OK: declares a function concept -template - concept bool F2(); // error: function concept is not a definition -template - constexpr bool F3(); -template - concept bool F3() { return true; } // error: redeclaration of a function as a concept -template - concept bool V1 = true; // OK: declares a variable concept -template - concept bool V2; // error: variable concept with no initializer -struct S { - template - static concept bool C = true; // error: concept declared in class scope -}; -\end{codeblock} -\exitexample - -\pnum -Every concept definition is implicitly defined to be a -\tcode{constexpr} declaration (\cxxref{dcl.constexpr}). -% -A concept definition shall not be declared with the -\tcode{thread_local}, \tcode{inline}, \tcode{friend}, or -\tcode{constexpr} specifiers, nor shall a concept definition have associated -constraints (\ref{temp.constr.decl}). - -\pnum -The definition of a function concept or the initializer of -a variable concept shall not include a reference to the concept being -declared. -% -\enterexample -\begin{codeblock} -template - concept bool F() { return F(); } // error -template - concept bool V = V; // error -\end{codeblock} -\exitexample - -\pnum -The first declared template parameter of a concept definition is its -\defn{prototype parameter}. -% -A \defn{variadic concept} is a concept whose prototype parameter -is a template parameter pack. - -\pnum -A function concept has the following restrictions: -\begin{itemize} -\item No \grammarterm{function-specifier}{}s shall - appear in its declaration (\cxxref{dcl.fct.spec}). - -\item The declared return type shall have the type \tcode{bool}. - -\item The declaration's parameter list shall be equivalent to an empty - parameter list. - -\item The declaration shall have a \grammarterm{function-body} equivalent -to \tcode{\{ return E; \}} where \tcode{E} is a -\grammarterm{constraint-expression} (\ref{temp.constr.expr}). -\end{itemize} -% -\enternote -Return type deduction requires the instantiation of the function -definition, but concept definitions are not instantiated; they -are normalized (\ref{temp.constr.decl}). -\exitnote -% -\enterexample -\begin{codeblock} -template - concept int F1() { return 0; } // error: return type is not bool -template - concept auto F2() { return true; } // error: return type is deduced -template - concept bool F3(T) { return true; } // error: not an empty parameter list -\end{codeblock} -\exitexample - -\pnum -A variable concept has the following restrictions: -\begin{itemize} -\item The declared type shall have the type \tcode{bool}. -\item The declaration shall have an initializer. -\item The initializer shall be a \grammarterm{constraint-expression}. -\end{itemize} -% -\enterexample -\begin{codeblock} -template - concept bool V1 = 3 + 4; // error: initializer is not a constraint-expression -concept bool V2 = 0; // error: not a template - -template concept bool C = true; - -template - concept bool V3 = true; // error: constrained template declared as a concept -\end{codeblock} -\exitexample - -\pnum -A program shall not declare an explicit instantiation (\ref{temp.explicit}), -an explicit specialization (\ref{temp.expl.spec}), or a partial specialization -of a concept definition. -% -\enternote -This prevents users from subverting the constraint system by providing a -meaning for a concept that differs from its original definition. -\exitnote -\end{quote} -\end{xremovedblock} -\end{quote} \ No newline at end of file diff --git a/src/declarators.tex b/src/declarators.tex index c3a691f..54bfcab 100644 --- a/src/declarators.tex +++ b/src/declarators.tex @@ -168,202 +168,3 @@ \added{or associated constraints (\ref{temp.constr.decl})} are part of the function type. \end{quote} - -Modify paragraph 17. Note that the footnote reference has been -omitted. - -\begin{quote} -\setcounter{Paras}{16} -\pnum -There is a syntactic ambiguity when an ellipsis occurs at the end of a -\grammarterm{parameter-declaration-clause} without a preceding comma. In this -case, the ellipsis is parsed as part of the \grammarterm{abstract-declarator} -if the type of the parameter either names a template parameter pack that has -not been expanded or contains -\removed{\tcode{auto}} -\added{a placeholder (\ref{dcl.spec.auto})}; -otherwise, it is parsed as part -of the \grammarterm{parameter-declaration-clause}. -\end{quote} - -Add the following paragraphs after paragraph 17. - -\begin{quote} -\begin{addedblock} -\pnum -An \defn{abbreviated function template} is a function declaration whose -parameter-type-list includes one or more placeholders (\ref{dcl.spec.auto}). -% -An abbreviated function template is equivalent to a function template -(\ref{temp.fct}) whose \grammarterm{template-parameter-list} -includes one invented \grammarterm{template-parameter} for each occurrence -of a placeholder in the \grammarterm{parameter-declaration-clause}, -in order of appearance, according to the rules below. -% -\enternote -Template parameters are also invented to deduce the type of a variable -or the return type of a function when the declared type contains placeholders -(\ref{dcl.spec.auto.deduct}). -\exitnote - -\pnum -Each template parameter is invented as follows. -\begin{itemize} -\item If the placeholder is designated by the \tcode{auto} -\grammarterm{type-specifier}, then the invented template -parameter is a type \grammarterm{template-parameter}. - -\item Otherwise, the placeholder is designated by a -\grammarterm{constrained-type-specifier}, and the invented -parameter is a \grammarterm{constrained-parameter} (\ref{temp.param}) whose -\grammarterm{qualified-concept-name} is that of the -\grammarterm{constrained-type-specifier}. - -\item If the placeholder appears in the \grammarterm{decl-specifier-seq} of a -function parameter pack (\cxxref{temp.variadic}), or the -\grammarterm{type-specifier-seq} of a \grammarterm{type-id} that is a pack -expansion, the invented template parameter is a -template parameter pack. -\end{itemize} -% -All placeholders designated by \grammarterm{constrained-type-specifier}{}s -whose corresponding \grammarterm{constrained-parameter}{s} would introduce -equivalent \grammarterm{constraint-expression}{s} (\ref{temp.param}), -using the rules for comparing expressions in \ref{temp.over.link}, have -the same invented template parameter. -% -\enterexample -\begin{codeblock} -namespace N { - template concept bool C = true; -} -template concept bool C = true; -template concept bool D = true; -template concept bool E = true; - -void abbr(C, D<0>); -\end{codeblock} -The \grammarterm{constrained-type-specifier}{}s \tcode{C} and \tcode{D<0>} -correspond to distinct invented template parameters in the declaration -of \tcode{abbr}. -\begin{codeblock} -void f0(C a, C b); -\end{codeblock} -The types of \tcode{a} and \tcode{b} are the same invented template -type parameter. -% -\begin{codeblock} -void f1(C& a, C* b); -\end{codeblock} -The type of \tcode{a} is a reference to an invented template type parameter -\tcode{T}, and the type of \tcode{b} is a pointer to \tcode{T}. -% -\begin{codeblock} -void f2(N::C a, C b); -void f3(D<0> a, D<1> b); -\end{codeblock} -In both functions, the parameters \tcode{a} and -\tcode{b} have different invented template type parameters. -% -\begin{codeblock} -void f4(E a, E<> b, E<0> c); -\end{codeblock} -The types of \tcode{a}, \tcode{b}, and \tcode{c} are the same because the -\grammarterm{constrained-type-specifier}{s} \tcode{E}, \tcode{E<>}, and -\tcode{E<0>} all associate the \grammarterm{constraint-expression} -\tcode{E}, where \tcode{T} is an invented template type parameter. -% -\begin{codeblock} -void f5(C head, C... tail); -\end{codeblock} -The types of \tcode{head} and \tcode{tail} are different. Their -respective introduced \grammarterm{constraint-expression}{s} are \tcode{C} -and \tcode{(C \&\& ...)}, where \tcode{T} is the template parameter invented -for \tcode{head} and \tcode{U} is the template parameter invented for -\tcode{tail} (\ref{temp.param}). - -\pnum -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}. -% -If the replacement of a placeholder with the name of a template parameter -results in an invalid parameter declaration, the program is ill-formed. -% -\enternote -Equivalent function template declarations declare the same function template -(\ref{temp.over.link}). -\exitnote -% -\enterexample -\begin{codeblock} -template class Vec { }; -template class Pair { }; -template class Tuple { }; - -void f1(const auto&, auto); -void f2(Vec...); -void f3(Tuple); -void f4(auto (auto::*)(auto)); - -template void f1(const T&, U); // redeclaration of \tcode{f1} -template void f2(Vec...); // redeclaration of \tcode{f2} -template void f3(Tuple); // redeclaration of \tcode{f3} -template void f4(T (U::*)(V)); // redeclaration of \tcode{f4} - -template concept bool C1 = true; -template concept bool C2 = true; -template concept bool C3 = true; -template concept bool C4 = true; - -void g1(const C1*, C2&); -void g2(Vec&); -void g3(C1&...); -void g4(Vec>); -void g5(C4...); -void g6(Tuple); -void g7(C4 p); -void g8(Tuple); - -template void g1(const T*, U&); // redeclaration of \tcode{g1} -template void g2(Vec&); // redeclaration of \tcode{g2} -template void g3(Ts&...); // redeclaration of \tcode{g3} -template T> void g4(Vec); // redeclaration of \tcode{g4} -template void g5(Ts...); // redeclaration of \tcode{g5} -template void g6(Tuple); // redeclaration of \tcode{g6} -template void g7(T); // redeclaration of \tcode{g7} -template void g8(Tuple); // redeclaration of \tcode{g8} -\end{codeblock} -\exitexample -% -\enterexample -\begin{codeblock} -template concept bool Num = true; - -void h(Num*); // error: invalid type in parameter declaration -\end{codeblock} -The equivalent declaration would have this form: -\begin{codeblock} -template void h(N*); // error: invalid type -\end{codeblock} -\exitexample - -\pnum -A function template can be an abbreviated function template. The -invented \grammarterm{template-parameter}{}s are appended to the -\grammarterm{template-parameter-list} after the explicitly declared -\grammarterm{template-parameter}{}s. - -\enterexample -\begin{codeblock} -template class Array { }; - -template void f(Array*); -template void f(Array*); // OK: redeclaration of \tcode{f(Array*)} -\end{codeblock} -\exitexample -\end{addedblock} -\end{quote} - - diff --git a/src/expressions.tex b/src/expressions.tex index d62aa4a..db254fb 100644 --- a/src/expressions.tex +++ b/src/expressions.tex @@ -37,13 +37,11 @@ \setcounter{subsection}{3} \rSec2[expr.prim.id]{Names} -Add \xremoved{a new paragraph} \xadded{new paragraphs} to the end of this -section. - -\setcounter{Paras}{2} +Add new paragraphs to the end of this section. \begin{quote} -\begin{xaddedblock} +\begin{addedblock} +\setcounter{Paras}{2} \pnum A \grammarterm{id-expression} that denotes the specialization of a concept (\ref{temp.concept}) result in a prvalue of type \tcode{bool}. @@ -52,9 +50,12 @@ (\ref{temp.constr.decl}) \emph{constraint-expression} is satisfied according to the rules in \ref{temp.constr.constr} and \tcode{false} otherwise. \enterexample +\begin{codeblock} template concept C = true; static_assert(C); // OK +\end{codeblock} \exitexample + \pnum \enternote A concept's constraints are also evaluated during the resolution of template @@ -63,10 +64,9 @@ (\ref{temp.constr.order}). \exitnote -\end{xaddedblock} +\end{addedblock} \end{quote} -% TODO: The wording "non-overloaded function declaration" is not right. \begin{quote} \begin{addedblock} \pnum @@ -90,168 +90,6 @@ \end{quote} -\setcounter{subsubsection}{1} -\rSec3[expr.prim.id.qual]{Qualified names} - -Add \tcode{auto} and \grammarterm{constrained-type-name} to the -\grammarterm{nested-name-specifier} grammar. - -\begin{quote} -\begin{bnf} -\nontermdef{nested-name-specifier}\br - \terminal{::}\br - type-name \terminal{::}\br - namespace-name \terminal{::}\br - decltype-specifier \terminal{::}\br - \added{\terminal{auto} \terminal{::}}\br - \added{constrained-type-name \terminal{::}}\br - nested-name-specifier identifier \terminal{::}\br - nested-name-specifier \terminal{template}\opt \terminal{::} -\end{bnf} -\end{quote} - -Add a new paragraph at the end of this section. - -\begin{quote} -\begin{addedblock} -\setcounter{Paras}{5} -\pnum -In a \grammarterm{nested-name-specifier} of the form \tcode{auto::} or -\tcode{C::}, where \tcode{C} is a \grammarterm{constrained-type-name}, -that \grammarterm{nested-name-specifier} designates a placeholder that -will be replaced later according to the rules for placeholder deduction in -\ref{dcl.spec.auto}. -% -If a placeholder designated by a \grammarterm{constrained-type-specifier} -is not a placeholder type, the program is ill-formed. -% -\enternote -A \grammarterm{constrained-type-specifier} can designate a placeholder for -a non-type or template (\ref{dcl.spec.auto.constr}). -\exitnote -% -The replacement type deduced for a placeholder shall be a class or -enumeration type. -% -\enterexample -\begin{codeblock} -template concept bool C = sizeof(T) == sizeof(int); -template concept bool D = true; - -struct S1 { int n; }; -struct S2 { char c; }; -struct S3 { struct X { using Y = int; }; }; - -int auto::* p1 = &S1::n; // \tcode{auto} deduced as \tcode{S1} -int D::* p2 = &S1::n; // error: \tcode{D} does not designate a placeholder type -int C::* p3 = &S1::n; // OK: \tcode{C} deduced as \tcode{S1} -char C::* p4 = &S2::c; // error: deduction fails because constraints are not satisfied - -void f(typename auto::X::Y); -f(S1()); // error: \tcode{auto} cannot be deduced from \tcode{S1()} -f(0); // OK -\end{codeblock} -In the declaration of \tcode{f}, the placeholder appears in a non-deduced -context (\cxxref{temp.deduct.type}). It may be replaced later through the -explicit specification of template arguments. -\exitexample -\end{addedblock} -\end{quote} - - -%% -%% Lambda expressions -%% -\setcounter{subsection}{4} -\rSec2[expr.prim.lambda]{Lambda expressions} - -Insert the following paragraph after paragraph 4 to define the -term ``generic lambda''. - -\begin{quote} -\begin{addedblock} -\setcounter{Paras}{4} -\pnum -A \defn{generic lambda} is a \grammarterm{lambda-expression} where one -or more placeholders (\ref{dcl.spec.auto}) appear in the parameter-type-list -of the \grammarterm{lambda-declarator}. -\end{addedblock} -\end{quote} - -\rSec3[expr.prim.lambda.closure]{Closure types} - -Modify paragraph 3 so that the meaning of a generic lambda is defined -in terms of its abbreviated member function template call operator. - -\begin{quote} -The closure type for a non-generic -\grammarterm{lambda-expression} has a public inline -function call operator (\cxxref{over.call}) -whose parameters and return type are described by the -\grammarterm{lambda-expression}'s -\grammarterm{parameter-declaration-clause} and -\grammarterm{trailing-return-type}, respectively. -% -\removed{ -For a generic lambda, the closure type has a public inline function call -operator member template (\cxxref{temp.mem}) whose -\grammarterm{template-parameter-list} consists of -one invented type \grammarterm{template-parameter} -for each occurrence of \tcode{auto} in the lambda's -\grammarterm{parameter-declaration-clause}, in order -of appearance. -% -The invented type \grammarterm{template-parameter} is -a parameter pack if the corresponding -\grammarterm{parameter-declaration declares} a -function parameter pack (\ref{dcl.fct}). -% -The return type and function parameters of the function call operator -template are derived from the -\grammarterm{lambda-expression}'s -\grammarterm{trailing-return-type} and -\grammarterm{parameter-declaration-clause} by -replacing each occurrence of \tcode{auto} in the -\grammarterm{decl-specifier}{}s of the -\grammarterm{parameter-declaration-clause} -with the name of the corresponding invented template-parameter. -} -% -\added{ -The closure type for a generic lambda has a public inline function call -operator member template that is an abbreviated function template whose -parameters and return type are derived from the -\grammarterm{lambda-expression}'s -\grammarterm{parameter-declaration-clause} and -\grammarterm{trailing-return-type} according to the -rules in (\ref{dcl.fct}). -} -\end{quote} - -Add the following example after those in paragraph 3 in the -\Cpp Standard. - -\begin{quote} -\begin{addedblock} -\enterexample -\begin{codeblock} -template concept bool C = true; - -auto gl = [](C& a, C* b) { a = *b; }; // OK: denotes a generic lambda - -struct Fun { - auto operator()(C& a, C* b) const { a = *b; } -} fun; -\end{codeblock} -\tcode{C} is a -\grammarterm{constrained-type-specifier}, -signifying that the lambda is generic. The generic lambda \tcode{gl} -and the function object \tcode{fun} have equivalent behavior when -called with the same arguments. -\exitexample -\end{addedblock} -\end{quote} - %% %% Requires expressions %% diff --git a/src/templates.tex b/src/templates.tex index 7744729..058943d 100644 --- a/src/templates.tex +++ b/src/templates.tex @@ -17,7 +17,6 @@ \nontermdef{template-declaration}\br \terminal{template} \terminal{<} template-parameter-list \terminal{>} \added{requires-clause\opt} declaration\br - \added{template-introduction declaration} \begin{addedblock} \nontermdef{requires-clause}\br @@ -26,24 +25,6 @@ \end{bnf} \end{quote} - -Add the following paragraphs after paragraph 6. - -\begin{quote} -\begin{addedblock} -\setcounter{Paras}{6} -\pnum -A \grammarterm{template-declaration} is written in terms of its template -parameters. These parameters are declared explicitly in a -\grammarterm{template-parameter-list} (\ref{temp.param}), or they are -introduced by a \grammarterm{template-introduction} (\ref{temp.intro}). -% -The optional \grammarterm{requires-clause} following a -\grammarterm{template-parameter-list} allows the specification of -constraints (\ref{temp.constr.decl}) on template arguments (\ref{temp.arg}). -\end{addedblock} -\end{quote} - %% %% Template parameters @@ -84,6 +65,13 @@ qualified-concept-name ... identifier\opt\br qualified-concept-name identifier\opt default-template-argument\opt +\nontermdef{qualified-concept-name}\br + nested-name-specifier\opt concept-name\br + nested-name-specifier\opt partial-concept-id + +\nontermdef{partial-concept-id}\br + concept-name \terminal{<} template-argument-list\opt \terminal{>} + \nontermdef{default-template-argument}\br \terminal{=} type-id\br \terminal{=} id-expression\br @@ -92,7 +80,7 @@ \end{bnf} \end{quote} -Insert a new paragraph after paragraph 1. +Insert new paragraphs after paragraph 1. \begin{quote} \begin{addedblock} @@ -101,9 +89,11 @@ declaration of a \grammarterm{constrained-parameter} and a \grammarterm{parameter-declaration}. % -If the \grammarterm{type-specifier-seq} of a \grammarterm{parameter-declaration} -is a \grammarterm{constrained-type-specifier} (\ref{dcl.spec.auto.constr}), -then the \grammarterm{template-parameter} is a \grammarterm{constrained-parameter}. +If the \grammarterm{type-specifier-seq} of a +\grammarterm{parameter-declaration} +is a \grammarterm{constrained-type-specifier}, +then the \grammarterm{template-parameter} is a +\grammarterm{constrained-parameter}. \end{addedblock} \end{quote} @@ -117,12 +107,10 @@ A \grammarterm{constrained-parameter} declares a template parameter whose kind (type, non-type, template) and type match that of the prototype parameter of the concept designated by the \grammarterm{qualified-concept-name} -(\ref{dcl.spec.auto.constr}) in the \grammarterm{constrained-parameter}. -% -\xremoved{The designated concept is selected by the rules for concept resolution -described in \ref{temp.constr.resolve}.} +in the \grammarterm{constrained-parameter}. % -Let \tcode{X} be the prototype parameter of the designated concept. +Let \tcode{X} be the prototype parameter of the concept designated by the +\grammarterm{concept-name} (\ref{temp.concept}). % The declared template parameter is determined by the kind of \tcode{X} (type, non-type, template) and the optional ellipsis in the @@ -173,27 +161,16 @@ \begin{itemize} \item First, form a template argument \tcode{A} from \tcode{P}. If \tcode{P} declares a template parameter pack (\cxxref{temp.variadic}) -and \tcode{C} is a variadic concept (\ref{dcl.spec.concept}), then \tcode{A} is +and \tcode{C} is a variadic concept (\ref{temp.concept}), then \tcode{A} is the pack expansion \tcode{P...}. Otherwise, \tcode{A} is the \grammarterm{id-expression} \tcode{P}. % FIXME: This does not guarantee that the expression has the same % namespace qualification as Q. -\item \xadded{Then, form an \grammarterm{id-expression} \tcode{E} as follows. +\item Then, form an \grammarterm{id-expression} \tcode{E} as follows. If \tcode{Q} is a \grammarterm{concept-name}, then \tcode{E} is \tcode{C}. Otherwise, \tcode{Q} is a \grammarterm{partial-concept-id} of the form - \tcode{C}, and \tcode{E} is \tcode{C}.} - -\item \xremoved{Then, form a \grammarterm{template-id} \tcode{TT} based on the -\grammarterm{qualified-concept-name} \tcode{Q}. If \tcode{Q} is -a \grammarterm{concept-name}, then \tcode{TT} is \tcode{C}. Otherwise, -\tcode{Q} is a \grammarterm{partial-concept-id} of the form -\tcode{C}, and \tcode{TT} is \tcode{C}}. - -\item \xremoved{Then, form an \grammarterm{expression} \tcode{E} as follows. -If \tcode{C} is a variable concept (\ref{dcl.spec.concept}), then \tcode{E} is the -\grammarterm{id-expression} \tcode{TT}. Otherwise, \tcode{C} is a function -concept and \tcode{E} is the function call \tcode{TT()}}. + \tcode{C}, and \tcode{E} is \tcode{C}. \item Finally, if \tcode{P} declares a template parameter pack and \tcode{C} is not a variadic concept, \tcode{E} is adjusted to be the @@ -247,187 +224,6 @@ \end{quote} -%% -%% Introduction of template parameters -%% -\rSec1[temp.intro]{Introduction of template parameters} - -Add this section after \ref{temp.param}. - -\begin{quote} -\begin{addedblock} -\pnum -A \grammarterm{template-introduction} provides a concise way of declaring -templates. - -\begin{bnf} -\nontermdef{template-introduction}\br - qualified-concept-name \terminal{\{} introduction-list \terminal{\}} - -\nontermdef{introduction-list}\br - introduced-parameter\br - introduction-list \terminal{,} introduced-parameter - -\nontermdef{introduced-parameter}\br - \terminal{...}\opt identifier -\end{bnf} - -A \grammarterm{template-introduction} declares a template whose -sequence of \grammarterm{template-parameter}{s} are derived from a -\grammarterm{qualified-concept-name} (\ref{dcl.spec.auto.constr}) and the -sequence of \grammarterm{introduced-parameter}{s} in its -\grammarterm{introduction-list}. - -\pnum -\xremoved{The concept designated by the \grammarterm{qualified-concept-name} is selected -by the concept resolution rules described in \ref{temp.constr.resolve}. Let -\tcode{C} be the designated concept. -% -The template parameters declared by a \grammarterm{template-introduction} -are derived from its \grammarterm{introduced-parameter}{s} and the -template parameter declarations of \tcode{C} to which those -\grammarterm{introduced-parameter}{s} are matched as wildcards according to -the rules in \ref{temp.constr.resolve}.} -% -\xadded{ -The template parameters declared by a \grammarterm{template-introduction} -are derived from the \grammarterm{qualified-concept-name} and its template -parameters using the following rules. -} -% -For each \grammarterm{introduced-parameter} \tcode{I}, declare a template -parameter using the following rules: -\begin{itemize} -\item Let \tcode{P} be the template parameter declaration in \tcode{C} - corresponding to \tcode{I}. If \tcode{P} does not declare a template - parameter pack (\cxxref{temp.variadic}), \tcode{I} shall not include - an ellipsis. - -\item If \tcode{P} declares a template parameter pack, adjust \tcode{P} - to be the pattern of that pack. - -\item Declare a template parameter according to the rules for declaring a - \grammarterm{constrained-parameter} in \ref{temp.param}, using - \tcode{P} as the prototype parameter and with no ellipsis. - -\item If \tcode{I} includes an ellipsis, then the declared template parameter - is a template parameter pack. -\end{itemize} -% -\enterexample -\begin{codeblock} -template concept C1 = true; -template class X> concept C2 = true; -template concept C3 = true; - -C1{A, B, ...C} // OK: \tcode{A} is declared as \tcode{typename A}, - struct S1; // \tcode{B} is declared as \tcode{int B}, and - // \tcode{C} is declared as \tcode{typename ... C} - -C2{T} void f(); // OK: \tcode{T} is declared as \tcode{template class T} -C2{...Ts} void g(); // error: the template parameter corresponding to \tcode{Ts} - // is not a template parameter pack - -C3{T} struct S2; // OK: \tcode{T} is declared as \tcode{typename T} -C3{...Ts} struct S2; // OK: \tcode{Ts} is declared as \tcode{typename ... Ts} -\end{codeblock} -\exitexample - - -\pnum -A concept referred to by a \grammarterm{qualified-concept-name} may have -template parameters with default template arguments. An -\grammarterm{introduction-list} may omit \grammarterm{identifier}{}s for a -corresponding template parameter if it has a default argument. -% -Only the \grammarterm{introduced-parameter}{}s are declared as template -parameters. -% -\enterexample -\begin{codeblock} -template concept C = true; - -C{T} void f(T); // OK: \tcode{f(T)} is a function template with - // a single template type parameter \tcode{T} -\end{codeblock} -\exitexample - -\pnum -An introduced template parameter does not have a default template argument -even if its corresponding template parameter does. -% -\enterexample -\begin{codeblock} -template concept P = true; - -P{T, N} struct Array { }; - -Array s1; // OK -Array s2; // error: \tcode{Array} takes two template arguments -\end{codeblock} -\exitexample - -\pnum -A \grammarterm{template-introduction} introduces a -\grammarterm{constraint-expression} (\ref{temp.constr.decl}). This -expression is derived from the \grammarterm{qualified-concept-name} -\tcode{C} in the \grammarterm{template-introduction} and the sequence of -\grammarterm{introduced-parameter}{s}. - -\begin{itemize} -\item First, form a sequence of template arguments \tcode{A1, A2, ..., A$N$} -corresponding to the \grammarterm{introduced-parameter}{s} -\tcode{P1, P2, ..., P$N$}. -% -For each \grammarterm{introduced-parameter} \tcode{P}, form a corresponding -template argument \tcode{A} as follows. If \tcode{P} includes an ellipsis, -then \tcode{A} is the pack expansion \tcode{P...} (\cxxref{temp.variadic}). -Otherwise, \tcode{A} is the \grammarterm{id-expression} \tcode{P}. - -% FIXME: This doesn't guarantee that the E has the same namespace specifier -% as the qualified form. -\item \xremoved{Then, form an expression \tcode{E} as follows. If \tcode{C} designates -a variable concept (\ref{dcl.spec.concept}), then \tcode{E} is the -\grammarterm{id-expression} -\tcode{C}. Otherwise, \tcode{C} designates a function concept and -\tcode{E} is the function call \tcode{C()}.} -\xadded{Then, form a \grammarterm{id-expression} \tcode{E} as -\tcode{C}.} -\end{itemize} -% -\tcode{E} is the introduced \grammarterm{constraint-expression}. -% -\enterexample -\begin{codeblock} -template concept C1 = true; -template concept C3 = true; - -C1{A, B} struct s1; // associates \tcode{C1} -C2{...Ts} struct s3; // associates \tcode{C2} -C2{X, ...Y} struct s4; // associates \tcode{C2} -\end{codeblock} -\exitexample - -\pnum -A template declared by a \grammarterm{template-introduction} can also be -an abbreviated function template (\ref{dcl.fct}). -% -The invented template parameters introduced by the placeholders in the -abbreviated function template are appended to the list of template parameters -declared by the \grammarterm{template-introduction}. -% -\enterexample -\begin{codeblock} -template concept C1 = true; - -C1{T} void f(T, auto); -template void f(T, U); // OK: redeclaration of \tcode{f(T, auto)} -\end{codeblock} -% -\exitexample -\end{addedblock} -\end{quote} - %% %% Names of template specializations @@ -993,10 +789,11 @@ %% \rSec2[temp.concept]{Concept definitions} -Add the following paragraph. +Add this section after \cxxref{temp.alias} in the \Cpp Standard. \begin{quote} -\begin{xaddedblock} +\begin{addedblock} + \pnum A \defn{concept} defines constraints on its template arguments. \begin{bnf} @@ -1010,22 +807,6 @@ \pnum A \grammarterm{concept-definition} declares its \grammarterm{identifier} to be a concept. The name of the concept is a \grammarterm{concept-name}. -\enterexample -\begin{codeblock} -template -concept C = requires(T x) { - { f(x) } -> T; -}; -template - requires C -T g(T x) { return f(x); } -int f(int n) { return n; } -void fn() { - g(0); // OK: \tcode{C} is satisfied - g((void*)0); // error: cannot call \tcode{g}, \tcode{C} is not satisfied -} -\end{codeblock} -\exitexample \pnum A \grammarterm{concept-definition} shall appear in the global scope or in a @@ -1037,8 +818,8 @@ specializes (\ref{temp.expl.spec}), or partially specializes a concept is ill-formed. \enternote -\emph{id-expression}s that denote a concept specialization are evaluated as -expressions (\ref{expr.prim.id}). +\emph{id-expression}{}s that denote a concept specialization are evaluated +(\ref{expr.prim.id}). \exitnote \pnum @@ -1046,7 +827,7 @@ \defn{prototype parameter}. A \defn{variadic concept} is a concept whose prototype parameter is a template parameter pack. -\end{xaddedblock} +\end{addedblock} \end{quote} %%