Skip to content

Commit b713e88

Browse files
authored
Merge 2019-11 CWG Motion 8
P1907R1 Inconsistencies with non-type template parameters
2 parents 862918f + 0c61ad1 commit b713e88

File tree

4 files changed

+120
-99
lines changed

4 files changed

+120
-99
lines changed

papers/nxxxx.md

+9
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ CWG motion 2: [P1234R5 "Paper name"](http://wg21.link/p1234r5), resolving 3 NB c
4343

4444
...
4545

46+
## Feature test macros
47+
48+
The feature test macro `__cpp_nontype_template_parameter_class` has been removed
49+
to indicate that the feature added by [P0732R2](http://wg21.link/p0732r2)
50+
is no longer present in the same form.
51+
52+
The value of the feature test macro `__cpp_nontype_template_args` has been increased
53+
to `201911L` to indicate support for [P1907R1](http://wg21.link/p1907r1).
54+
4655
## Disposition of editorial NB comments on C++ 2020 CD1
4756

4857
Listed below are draft disposition for all comments that were

source/classes.tex

-24
Original file line numberDiff line numberDiff line change
@@ -6700,30 +6700,6 @@
67006700
the defaulted three-way comparison operator function is defined as deleted.
67016701
\end{note}
67026702

6703-
\pnum
6704-
\indextext{structural comparison operator|see{operator, structural comparison}}%
6705-
A type \tcode{C} has \defnadj{strong structural}{equality} if,
6706-
given a glvalue \tcode{x} of type \tcode{const C}, either:
6707-
\begin{itemize}
6708-
\item
6709-
\tcode{C} is a non-class type and
6710-
\tcode{x <=> x} is a valid expression
6711-
of type \tcode{std::strong_ordering} or \tcode{std::strong_equality}, or
6712-
6713-
\item
6714-
\tcode{C} is a class type
6715-
where all of the following hold:
6716-
\begin{itemize}
6717-
\item All of \tcode{C}'s base class subobjects and non-static data members
6718-
have strong structural equality.
6719-
\item \tcode{C} has no mutable or volatile non-static data members.
6720-
\item At the end of the definition of \tcode{C},
6721-
overload resolution performed for the expression \tcode{x == x} succeeds and
6722-
finds either a friend or public member \tcode{==} operator
6723-
that is defined as defaulted in the definition of \tcode{C}.
6724-
\end{itemize}
6725-
\end{itemize}
6726-
67276703
\pnum
67286704
The direct base class subobjects of \tcode{C},
67296705
in the order of their declaration in the \grammarterm{base-specifier-list} of \tcode{C},

source/preprocessor.tex

+1-2
Original file line numberDiff line numberDiff line change
@@ -1668,9 +1668,8 @@
16681668
\defnxname{cpp_modules} & \tcode{201907L} \\ \rowsep
16691669
\defnxname{cpp_namespace_attributes} & \tcode{201411L} \\ \rowsep
16701670
\defnxname{cpp_noexcept_function_type} & \tcode{201510L} \\ \rowsep
1671-
\defnxname{cpp_nontype_template_args} & \tcode{201411L} \\ \rowsep
1671+
\defnxname{cpp_nontype_template_args} & \tcode{201911L} \\ \rowsep
16721672
\defnxname{cpp_nontype_template_parameter_auto} & \tcode{201606L} \\ \rowsep
1673-
\defnxname{cpp_nontype_template_parameter_class} & \tcode{201806L} \\ \rowsep
16741673
\defnxname{cpp_nsdmi} & \tcode{200809L} \\ \rowsep
16751674
\defnxname{cpp_range_based_for} & \tcode{201603L} \\ \rowsep
16761675
\defnxname{cpp_raw_strings} & \tcode{200710L} \\ \rowsep

source/templates.tex

+110-73
Original file line numberDiff line numberDiff line change
@@ -367,28 +367,31 @@
367367
A non-type \grammarterm{template-parameter}
368368
shall have one of the following (optionally cv-qualified) types:
369369
\begin{itemize}
370-
\item a literal type that
371-
has strong structural equality\iref{class.compare.default},
372-
373-
\item an lvalue reference type,
374-
370+
\item a structural type (see below),
375371
\item a type that contains a placeholder type\iref{dcl.spec.auto}, or
376-
377372
\item a placeholder for a deduced class type\iref{dcl.type.class.deduct}.
378373
\end{itemize}
379-
380-
\pnum
381-
\begin{note}
382-
Other types are disallowed either explicitly below or implicitly by
383-
the rules governing the form of
384-
\grammarterm{template-argument}{s}\iref{temp.arg}.
385-
\end{note}
386374
The top-level
387375
\grammarterm{cv-qualifier}{s}
388376
on the
389377
\grammarterm{template-parameter}
390378
are ignored when determining its type.
391379

380+
\pnum
381+
A \defnadj{structural}{type} is one of the following:
382+
\begin{itemize}
383+
\item a scalar type, or
384+
\item an lvalue reference type, or
385+
\item a literal class type with the following properties:
386+
\begin{itemize}
387+
\item
388+
all base classes and non-static data members are public and non-mutable and
389+
\item
390+
the types of all bases classes and non-static data members are
391+
structural types or (possibly multi-dimensional) array thereof.
392+
\end{itemize}
393+
\end{itemize}
394+
392395
\pnum
393396
An \grammarterm{id-expression} naming
394397
a non-type \grammarterm{template-parameter} of class type \tcode{T}
@@ -399,6 +402,7 @@
399402
to the type of the \grammarterm{template-parameter}.
400403
All such template parameters in the program of the same type
401404
with the same value denote the same template parameter object.
405+
A template parameter object shall have constant destruction\iref{expr.const}.
402406
\begin{note}
403407
If an \grammarterm{id-expression} names
404408
a non-type non-reference \grammarterm{template-parameter},
@@ -409,9 +413,9 @@
409413
\begin{example}
410414
\begin{codeblock}
411415
using X = int;
412-
struct A { friend bool operator==(const A&, const A&) = default; };
416+
struct A {};
413417
template<const X& x, int i, A a> void f() {
414-
i++; // error: change of template-parameter value
418+
i++; // error: change of \grammarterm{template-parameter} value
415419

416420
&x; // OK
417421
&i; // error: address of non-reference template-parameter
@@ -424,16 +428,17 @@
424428
\end{example}
425429

426430
\pnum
431+
\begin{note}
427432
A non-type
428433
\grammarterm{template-parameter}
429-
shall not be declared to have floating-point or void type.
434+
cannot be declared to have type \cv{} \tcode{void}.
430435
\begin{example}
431436
\begin{codeblock}
432-
template<double d> class X; // error
433-
template<double* pd> class Y; // OK
434-
template<double& rd> class Z; // OK
437+
template<void v> class X; // error
438+
template<void* pv> class Y; // OK
435439
\end{codeblock}
436440
\end{example}
441+
\end{note}
437442

438443
\pnum
439444
A non-type
@@ -1184,26 +1189,27 @@
11841189
for a non-type \grammarterm{template-parameter}
11851190
shall be a converted constant expression\iref{expr.const}
11861191
of the type of the \grammarterm{template-parameter}.
1192+
\begin{note}
1193+
If the \grammarterm{template-argument}
1194+
represents a set of overloaded functions
1195+
(or a pointer or member pointer to such),
1196+
the matching function is selected from the set\iref{over.over}.
1197+
\end{note}
1198+
1199+
\pnum
11871200
For a non-type \grammarterm{template-parameter} of reference or pointer type,
11881201
or for each non-static data member of reference or pointer type
11891202
in a non-type \grammarterm{template-parameter} of class type or subobject thereof,
11901203
the reference or pointer value shall not refer to
11911204
or be the address of (respectively):
11921205
\begin{itemize}
1193-
\item a subobject\iref{intro.object},
11941206
\item a temporary object\iref{class.temporary},
11951207
\item a string literal\iref{lex.string},
1196-
\item the result of a \tcode{typeid} expression\iref{expr.typeid}, or
1197-
\item a predefined \mname{func} variable\iref{dcl.fct.def.general}.
1208+
\item the result of a \tcode{typeid} expression\iref{expr.typeid},
1209+
\item a predefined \mname{func} variable\iref{dcl.fct.def.general}, or
1210+
\item a subobject\iref{intro.object} of one of the above.
11981211
\end{itemize}
11991212

1200-
\begin{note}
1201-
If the \grammarterm{template-argument}
1202-
represents a set of overloaded functions
1203-
(or a pointer or member pointer to such),
1204-
the matching function is selected from the set\iref{over.over}.
1205-
\end{note}
1206-
12071213
\pnum
12081214
\begin{example}
12091215
\begin{codeblock}
@@ -1228,9 +1234,10 @@
12281234
A<&f> a; // selects \tcode{f(int)}
12291235

12301236
template<auto n> struct B { @\commentellip@ };
1231-
B<5> b1; // OK: template parameter type is \tcode{int}
1232-
B<'a'> b2; // OK: template parameter type is \tcode{char}
1233-
B<2.5> b3; // error: template parameter type cannot be \tcode{double}
1237+
B<5> b1; // OK, template parameter type is \tcode{int}
1238+
B<'a'> b2; // OK, template parameter type is \tcode{char}
1239+
B<2.5> b3; // OK, template parameter type is \tcode{double}
1240+
B<void(0)> b4; // error: template parameter type cannot be \tcode{void}
12341241
\end{codeblock}
12351242
\end{example}
12361243

@@ -1245,40 +1252,21 @@
12451252
@\commentellip@
12461253
};
12471254

1248-
X<const char*, "Studebaker"> x; // error: string literal as template-argument
1255+
X<const char*, "Studebaker"> x; // error: string literal as \grammarterm{template-argument}
1256+
X<const char*, "Knope" + 1> x2; // error: subobject of string literal as \grammarterm{template-argument}
12491257

12501258
const char p[] = "Vivisectionist";
12511259
X<const char*, p> y; // OK
12521260

12531261
struct A {
12541262
constexpr A(const char*) {}
1255-
friend bool operator==(const A&, const A&) = default;
12561263
};
12571264

12581265
X<A, "Pyrophoricity"> z; // OK, string literal is a constructor argument to \tcode{A}
12591266
\end{codeblock}
12601267
\end{example}
12611268
\end{note}
12621269

1263-
\pnum
1264-
\begin{note}
1265-
The address of an array element or non-static data member is not an acceptable
1266-
\grammarterm{template-argument}.
1267-
\begin{example}
1268-
\begin{codeblock}
1269-
template<int* p> class X { };
1270-
1271-
int a[10];
1272-
struct S { int m; static int s; } s;
1273-
1274-
X<&a[2]> x3; // error: address of array element
1275-
X<&s.m> x4; // error: address of non-static member
1276-
X<&s.s> x5; // OK: address of static member
1277-
X<&S::s> x6; // OK: address of static member
1278-
\end{codeblock}
1279-
\end{example}
1280-
\end{note}
1281-
12821270
\pnum
12831271
\begin{note}
12841272
A temporary object
@@ -1291,10 +1279,16 @@
12911279
\begin{codeblock}
12921280
template<const int& CRI> struct B { @\commentellip@ };
12931281

1294-
B<1> b2; // error: temporary would be required for template argument
1282+
B<1> b1; // error: temporary would be required for template argument
12951283

12961284
int c = 1;
1297-
B<c> b1; // OK
1285+
B<c> b2; // OK
1286+
1287+
struct X { int n; };
1288+
struct Y { const int &r; };
1289+
template<Y y> struct C { @\commentellip@ };
1290+
C<Y{X{1}.n}> c; // error: subobject of temporary object used to initialize
1291+
// reference member of template parameter
12981292
\end{codeblock}
12991293
\end{example}
13001294
\end{note}
@@ -1939,25 +1933,68 @@
19391933
Two \grammarterm{template-id}{s} refer to the same
19401934
class, function, or variable if
19411935
\begin{itemize}
1942-
\item {their \grammarterm{template-name}{s},
1943-
\grammarterm{operator-function-id}{s}, or \grammarterm{literal-operator-id}{s}
1944-
refer to the same template and}
1945-
\item {their corresponding type \grammarterm{template-argument}{s} are the
1946-
same type and}
1947-
\item {their corresponding non-type \grammarterm{template-argument}{s} of
1948-
pointer-to-member type refer to the same class member or are both the null member
1949-
pointer value and}
1950-
\item {their corresponding non-type \grammarterm{template-argument}{s} of
1951-
reference type refer to the same object or function and}
1952-
\item {their remaining corresponding
1953-
non-type \grammarterm{template-argument}{s}
1954-
have the same type and value
1955-
after conversion to the type of the \grammarterm{template-parameter},
1956-
where they are considered to have the same value if they compare equal
1957-
with the \tcode{==} operator\iref{expr.eq}, and}
1958-
\item {their corresponding template \grammarterm{template-argument}{s} refer
1959-
to the same template.}
1936+
\item
1937+
their \grammarterm{template-name}{s},
1938+
\grammarterm{operator-function-id}{s}, or
1939+
\grammarterm{literal-operator-id}{s}
1940+
refer to the same template, and
1941+
1942+
\item
1943+
their corresponding type \grammarterm{template-argument}{s}
1944+
are the same type, and
1945+
1946+
\item
1947+
their corresponding non-type \grammarterm{template-argument}{s}
1948+
are template-argument-equivalent (see below)
1949+
after conversion to the type of the \grammarterm{template-parameter}, and
1950+
1951+
\item
1952+
their corresponding template \grammarterm{template-argument}{s}
1953+
refer to the same template.
1954+
\end{itemize}
1955+
1956+
\pnum
1957+
Two values are \defn{template-argument-equivalent} if
1958+
they are of the same type and
1959+
\begin{itemize}
1960+
\item
1961+
they are of integral type and their values are the same, or
1962+
1963+
\item
1964+
they are of floating-point type and their values are identical, or
1965+
1966+
\item
1967+
they are of type \tcode{std::nullptr_t}, or
1968+
1969+
\item
1970+
they are of enumeration type and their values are the same,%
1971+
\footnote{The identity of enumerators is not preserved.} or
1972+
1973+
\item
1974+
they are of pointer type and they have the same pointer value, or
1975+
1976+
\item
1977+
they are of pointer-to-member type and they refer to the same class member
1978+
or are both the null member pointer value, or
1979+
1980+
\item
1981+
they are of reference type and they refer to the same object or function, or
1982+
1983+
\item
1984+
they are of array type and their corresponding elements are template-argument-equivalent,%
1985+
\footnote{An array as a \grammarterm{template-parameter} decays to a pointer.} or
1986+
1987+
\item
1988+
they are of union type and either
1989+
they both have no active member or
1990+
they have the same active member and their active members are template-argument-equivalent, or
1991+
1992+
\item
1993+
they are of class type and
1994+
their corresponding direct subobjects and reference members are template-argument-equivalent.
19601995
\end{itemize}
1996+
1997+
\pnum
19611998
\begin{example}
19621999
\begin{codeblock}
19632000
template<class E, int size> class buffer { @\commentellip@ };

0 commit comments

Comments
 (0)