From cf2571463a5b0601f034837b04d43fd736e7200e Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 12 Nov 2019 18:09:52 -0800 Subject: [PATCH 1/3] P1907R1 Inconsistencies with non-type template parameters Moved definition of "structural type" next to its only use. Removed unused name T for type of an enumeration value in definition of template-argument-equivalent. Also fixes NB US 092, US 093, US 100, US 102, US 114 (C++20 CD). --- source/classes.tex | 24 -------- source/templates.tex | 130 +++++++++++++++++++++++++++++-------------- 2 files changed, 89 insertions(+), 65 deletions(-) diff --git a/source/classes.tex b/source/classes.tex index 7bf6865055..dcadf27055 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -6700,30 +6700,6 @@ the defaulted three-way comparison operator function is defined as deleted. \end{note} -\pnum -\indextext{structural comparison operator|see{operator, structural comparison}}% -A type \tcode{C} has \defnadj{strong structural}{equality} if, -given a glvalue \tcode{x} of type \tcode{const C}, either: -\begin{itemize} -\item -\tcode{C} is a non-class type and -\tcode{x <=> x} is a valid expression -of type \tcode{std::strong_ordering} or \tcode{std::strong_equality}, or - -\item -\tcode{C} is a class type -where all of the following hold: -\begin{itemize} -\item All of \tcode{C}'s base class subobjects and non-static data members -have strong structural equality. -\item \tcode{C} has no mutable or volatile non-static data members. -\item At the end of the definition of \tcode{C}, -overload resolution performed for the expression \tcode{x == x} succeeds and -finds either a friend or public member \tcode{==} operator -that is defined as defaulted in the definition of \tcode{C}. -\end{itemize} -\end{itemize} - \pnum The direct base class subobjects of \tcode{C}, in the order of their declaration in the \grammarterm{base-specifier-list} of \tcode{C}, diff --git a/source/templates.tex b/source/templates.tex index 474138e41c..bc385a32ce 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -367,28 +367,31 @@ A non-type \grammarterm{template-parameter} shall have one of the following (optionally cv-qualified) types: \begin{itemize} -\item a literal type that - has strong structural equality\iref{class.compare.default}, - -\item an lvalue reference type, - +\item a structural type (see below), \item a type that contains a placeholder type\iref{dcl.spec.auto}, or - \item a placeholder for a deduced class type\iref{dcl.type.class.deduct}. \end{itemize} - -\pnum -\begin{note} -Other types are disallowed either explicitly below or implicitly by -the rules governing the form of -\grammarterm{template-argument}{s}\iref{temp.arg}. -\end{note} The top-level \grammarterm{cv-qualifier}{s} on the \grammarterm{template-parameter} are ignored when determining its type. +\pnum +A \defnadj{structural}{type} is one of the following: +\begin{itemize} +\item a scalar type, or +\item an lvalue reference type, or +\item a literal class type with the following properties: +\begin{itemize} +\item +all base classes and non-static data members are public and non-mutable and +\item +the types of all bases classes and non-static data members are +structural types or (possibly multi-dimensional) array thereof. +\end{itemize} +\end{itemize} + \pnum An \grammarterm{id-expression} naming a non-type \grammarterm{template-parameter} of class type \tcode{T} @@ -399,6 +402,7 @@ to the type of the \grammarterm{template-parameter}. All such template parameters in the program of the same type with the same value denote the same template parameter object. +A template parameter object shall have constant destruction\iref{expr.const}. \begin{note} If an \grammarterm{id-expression} names a non-type non-reference \grammarterm{template-parameter}, @@ -1184,26 +1188,27 @@ for a non-type \grammarterm{template-parameter} shall be a converted constant expression\iref{expr.const} of the type of the \grammarterm{template-parameter}. +\begin{note} +If the \grammarterm{template-argument} +represents a set of overloaded functions +(or a pointer or member pointer to such), +the matching function is selected from the set\iref{over.over}. +\end{note} + +\pnum For a non-type \grammarterm{template-parameter} of reference or pointer type, or for each non-static data member of reference or pointer type in a non-type \grammarterm{template-parameter} of class type or subobject thereof, the reference or pointer value shall not refer to or be the address of (respectively): \begin{itemize} -\item a subobject\iref{intro.object}, \item a temporary object\iref{class.temporary}, \item a string literal\iref{lex.string}, -\item the result of a \tcode{typeid} expression\iref{expr.typeid}, or -\item a predefined \mname{func} variable\iref{dcl.fct.def.general}. +\item the result of a \tcode{typeid} expression\iref{expr.typeid}, +\item a predefined \mname{func} variable\iref{dcl.fct.def.general}, or +\item a subobject\iref{intro.object} of one of the above. \end{itemize} -\begin{note} -If the \grammarterm{template-argument} -represents a set of overloaded functions -(or a pointer or member pointer to such), -the matching function is selected from the set\iref{over.over}. -\end{note} - \pnum \begin{example} \begin{codeblock} @@ -1939,25 +1944,68 @@ Two \grammarterm{template-id}{s} refer to the same class, function, or variable if \begin{itemize} -\item {their \grammarterm{template-name}{s}, -\grammarterm{operator-function-id}{s}, or \grammarterm{literal-operator-id}{s} -refer to the same template and} -\item {their corresponding type \grammarterm{template-argument}{s} are the -same type and} -\item {their corresponding non-type \grammarterm{template-argument}{s} of -pointer-to-member type refer to the same class member or are both the null member -pointer value and} -\item {their corresponding non-type \grammarterm{template-argument}{s} of -reference type refer to the same object or function and} -\item {their remaining corresponding -non-type \grammarterm{template-argument}{s} -have the same type and value -after conversion to the type of the \grammarterm{template-parameter}, -where they are considered to have the same value if they compare equal -with the \tcode{==} operator\iref{expr.eq}, and} -\item {their corresponding template \grammarterm{template-argument}{s} refer -to the same template.} +\item +their \grammarterm{template-name}{s}, +\grammarterm{operator-function-id}{s}, or +\grammarterm{literal-operator-id}{s} +refer to the same template, and + +\item +their corresponding type \grammarterm{template-argument}{s} +are the same type, and + +\item +their corresponding non-type \grammarterm{template-argument}{s} +are template-argument-equivalent (see below) +after conversion to the type of the \grammarterm{template-parameter}, and + +\item +their corresponding template \grammarterm{template-argument}{s} +refer to the same template. +\end{itemize} + +\pnum +Two values are \defn{template-argument-equivalent} if +they are of the same type and +\begin{itemize} +\item +they are of integral type and their values are the same, or + +\item +they are of floating-point type and their values are identical, or + +\item +they are of type \tcode{std::nullptr_t}, or + +\item +they are of enumeration type and their values are the same,% +\footnote{The identity of enumerators is not preserved.} or + +\item +they are of pointer type and they have the same pointer value, or + +\item +they are of pointer-to-member type and they refer to the same class member +or are both the null member pointer value, or + +\item +they are of reference type and they refer to the same object or function, or + +\item +they are of array type and their corresponding elements are template-argument-equivalent,% +\footnote{An array as a \grammarterm{template-parameter} decays to a pointer.} or + +\item +they are of union type and either +they both have no active member or +they have the same active member and their active members are template-argument-equivalent, or + +\item +they are of class type and +their corresponding direct subobjects and reference members are template-argument-equivalent. \end{itemize} + +\pnum \begin{example} \begin{codeblock} template class buffer { @\commentellip@ }; From 6ec7eb80fcf30c44632bba59826e4f26c53688ee Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 12 Nov 2019 19:11:20 -0800 Subject: [PATCH 2/3] [temp.param] [temp.arg.nontype] Update examples and redundant duplicated wording to match P1907R1. --- source/templates.tex | 53 ++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/source/templates.tex b/source/templates.tex index bc385a32ce..06e5b1312b 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -413,9 +413,9 @@ \begin{example} \begin{codeblock} using X = int; -struct A { friend bool operator==(const A&, const A&) = default; }; +struct A {}; template void f() { - i++; // error: change of template-parameter value + i++; // error: change of \grammarterm{template-parameter} value &x; // OK &i; // error: address of non-reference template-parameter @@ -428,16 +428,17 @@ \end{example} \pnum +\begin{note} A non-type \grammarterm{template-parameter} -shall not be declared to have floating-point or void type. +cannot be declared to have type \cv{} \tcode{void}. \begin{example} \begin{codeblock} -template class X; // error -template class Y; // OK -template class Z; // OK +template class X; // error +template class Y; // OK \end{codeblock} \end{example} +\end{note} \pnum A non-type @@ -1233,9 +1234,10 @@ A<&f> a; // selects \tcode{f(int)} template struct B { @\commentellip@ }; -B<5> b1; // OK: template parameter type is \tcode{int} -B<'a'> b2; // OK: template parameter type is \tcode{char} -B<2.5> b3; // error: template parameter type cannot be \tcode{double} +B<5> b1; // OK, template parameter type is \tcode{int} +B<'a'> b2; // OK, template parameter type is \tcode{char} +B<2.5> b3; // OK, template parameter type is \tcode{double} +B b4; // error: template parameter type cannot be \tcode{void} \end{codeblock} \end{example} @@ -1250,14 +1252,14 @@ @\commentellip@ }; -X x; // error: string literal as template-argument +X x; // error: string literal as \grammarterm{template-argument} +X x2; // error: subobject of string literal as \grammarterm{template-argument} const char p[] = "Vivisectionist"; X y; // OK struct A { constexpr A(const char*) {} - friend bool operator==(const A&, const A&) = default; }; X z; // OK, string literal is a constructor argument to \tcode{A} @@ -1265,25 +1267,6 @@ \end{example} \end{note} -\pnum -\begin{note} -The address of an array element or non-static data member is not an acceptable -\grammarterm{template-argument}. -\begin{example} -\begin{codeblock} -template class X { }; - -int a[10]; -struct S { int m; static int s; } s; - -X<&a[2]> x3; // error: address of array element -X<&s.m> x4; // error: address of non-static member -X<&s.s> x5; // OK: address of static member -X<&S::s> x6; // OK: address of static member -\end{codeblock} -\end{example} -\end{note} - \pnum \begin{note} A temporary object @@ -1296,10 +1279,16 @@ \begin{codeblock} template struct B { @\commentellip@ }; -B<1> b2; // error: temporary would be required for template argument +B<1> b1; // error: temporary would be required for template argument int c = 1; -B b1; // OK +B b2; // OK + +struct X { int n; }; +struct Y { const int &r; }; +template struct C { @\commentellip@ }; +C c; // error: subobject of temporary object used to initialize + // reference member of template parameter \end{codeblock} \end{example} \end{note} From 0c61ad109ef8847f9bcaea4cb725537fda0ba99d Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 15 Nov 2019 16:57:10 -0800 Subject: [PATCH 3/3] [cpp.predefined] Bump value of __cpp_nontype_template_args to 201911L for P1907R1, and remove __cpp_nontype_template_parameter_class to indicate that the feature added by P0732R2 is no longer present in that form. --- papers/nxxxx.md | 9 +++++++++ source/preprocessor.tex | 3 +-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/papers/nxxxx.md b/papers/nxxxx.md index d6a43360ce..d955672db0 100644 --- a/papers/nxxxx.md +++ b/papers/nxxxx.md @@ -43,6 +43,15 @@ CWG motion 2: [P1234R5 "Paper name"](http://wg21.link/p1234r5), resolving 3 NB c ... +## Feature test macros + +The feature test macro `__cpp_nontype_template_parameter_class` has been removed +to indicate that the feature added by [P0732R2](http://wg21.link/p0732r2) +is no longer present in the same form. + +The value of the feature test macro `__cpp_nontype_template_args` has been increased +to `201911L` to indicate support for [P1907R1](http://wg21.link/p1907r1). + ## Disposition of editorial NB comments on C++ 2020 CD1 Listed below are draft disposition for all comments that were diff --git a/source/preprocessor.tex b/source/preprocessor.tex index 0696fdbb6b..23ad1789c0 100644 --- a/source/preprocessor.tex +++ b/source/preprocessor.tex @@ -1668,9 +1668,8 @@ \defnxname{cpp_modules} & \tcode{201907L} \\ \rowsep \defnxname{cpp_namespace_attributes} & \tcode{201411L} \\ \rowsep \defnxname{cpp_noexcept_function_type} & \tcode{201510L} \\ \rowsep -\defnxname{cpp_nontype_template_args} & \tcode{201411L} \\ \rowsep +\defnxname{cpp_nontype_template_args} & \tcode{201911L} \\ \rowsep \defnxname{cpp_nontype_template_parameter_auto} & \tcode{201606L} \\ \rowsep -\defnxname{cpp_nontype_template_parameter_class} & \tcode{201806L} \\ \rowsep \defnxname{cpp_nsdmi} & \tcode{200809L} \\ \rowsep \defnxname{cpp_range_based_for} & \tcode{201603L} \\ \rowsep \defnxname{cpp_raw_strings} & \tcode{200710L} \\ \rowsep