|
365 | 365 | \end{note}
|
366 | 366 |
|
367 | 367 | \pnum
|
368 |
| -A non-type |
369 |
| -\grammarterm{template-parameter} |
370 |
| -shall have one of the following (optionally |
371 |
| -cv-qualified) |
372 |
| -types: |
| 368 | +A non-type \grammarterm{template-parameter} |
| 369 | +shall have one of the following (optionally cv-qualified) types: |
373 | 370 |
|
374 | 371 | \begin{itemize}
|
375 |
| -\item integral or enumeration type, |
376 |
| - |
377 |
| -\item pointer to object or pointer to function, |
| 372 | +\item a type that is literal, |
| 373 | +has strong structural equality\iref{class.compare.default}, |
| 374 | +has no \tcode{mutable} or \tcode{volatile} subobjects, |
| 375 | +and in which if there is a defaulted member \tcode{operator<=>}, |
| 376 | +then it is declared public, |
378 | 377 |
|
379 |
| -\item lvalue reference to object or lvalue reference to function, |
| 378 | +\item an lvalue reference type, |
380 | 379 |
|
381 |
| -\item pointer to member, |
| 380 | +\item a type that contains a placeholder type\iref{dcl.spec.auto}, or |
382 | 381 |
|
383 |
| -\item \tcode{std::nullptr_t}, or |
384 |
| - |
385 |
| -\item a type that contains a placeholder type\iref{dcl.spec.auto}. |
| 382 | +\item a placeholder for a deduced class type\iref{dcl.type.class.deduct}. |
386 | 383 | \end{itemize}
|
387 | 384 |
|
388 | 385 | \pnum
|
|
398 | 395 | are ignored when determining its type.
|
399 | 396 |
|
400 | 397 | \pnum
|
401 |
| -A non-type non-reference |
402 |
| -\grammarterm{template-parameter} |
403 |
| -is a prvalue. |
404 |
| -It shall not be assigned to or in any other way have its value changed. |
405 |
| -A non-type non-reference |
406 |
| -\grammarterm{template-parameter} |
407 |
| -cannot have its address taken. |
408 |
| -When a non-type non-reference |
409 |
| -\grammarterm{template-parameter} |
| 398 | +When a non-type \grammarterm{template-parameter} |
| 399 | +of non-reference and non-class type |
410 | 400 | is used as an initializer for a reference, a temporary is always used.
|
| 401 | +An \grammarterm{id-expression} naming |
| 402 | +a non-type \grammarterm{template-parameter} of class type \tcode{T} |
| 403 | +denotes a static storage duration object of type \tcode{const T}, |
| 404 | +known as a \defn{template parameter object}, |
| 405 | +whose value is that of the corresponding template argument |
| 406 | +after it has been converted |
| 407 | +to the type of the \grammarterm{template-parameter}. |
| 408 | +All such template parameters in the program of the same type |
| 409 | +with the same value denote the same template parameter object. |
| 410 | +\begin{note} |
| 411 | +If an \grammarterm{id-expression} names |
| 412 | +a non-type non-reference \grammarterm{template-parameter}, |
| 413 | +then it is a prvalue if it has non-class type. |
| 414 | +Otherwise, if it is of class type \tcode{T}, |
| 415 | +it is an lvalue and has type \tcode{const T}\iref{expr.prim.id.unqual}. |
| 416 | +\end{note} |
411 | 417 | \begin{example}
|
412 | 418 |
|
413 | 419 | \begin{codeblock}
|
414 |
| -template<const X& x, int i> void f() { |
| 420 | +struct A { auto operator<=>(A, A) = default; }; |
| 421 | +template<const X& x, int i, A a> void f() { |
415 | 422 | i++; // error: change of template-parameter value
|
416 | 423 |
|
417 | 424 | &x; // OK
|
418 | 425 | &i; // error: address of non-reference template-parameter
|
419 |
| - |
| 426 | + &a; // OK |
420 | 427 | int& ri = i; // error: non-const reference bound to temporary
|
421 | 428 | const int& cri = i; // OK: const reference bound to temporary
|
| 429 | + const A& ra = a; // OK: const reference bound to a template parameter object |
422 | 430 | }
|
423 | 431 | \end{codeblock}
|
424 | 432 | \end{example}
|
|
1284 | 1292 | \rSec2[temp.arg.nontype]{Template non-type arguments}
|
1285 | 1293 |
|
1286 | 1294 | \pnum
|
1287 |
| -If the type of a \grammarterm{template-parameter} |
1288 |
| -contains a placeholder type~(\ref{dcl.spec.auto}, \ref{temp.param}), |
1289 |
| -the deduced parameter type is determined |
1290 |
| -from the type of the \grammarterm{template-argument} |
1291 |
| -by placeholder type deduction\iref{dcl.type.auto.deduct}. |
| 1295 | +If the type \tcode{T} of a \grammarterm{template-parameter}\iref{temp.param} |
| 1296 | +contains a placeholder type\iref{dcl.spec.auto} |
| 1297 | +or a placeholder for a deduced class type\iref{dcl.type.class.deduct}, |
| 1298 | +the type of the parameter is the type deduced |
| 1299 | +for the variable \tcode{x} in the invented declaration |
| 1300 | +\begin{codeblock} |
| 1301 | + T x = @\grammarterm{template-argument}\itcorr[-1]@ ; |
| 1302 | +\end{codeblock} |
1292 | 1303 | If a deduced parameter type is not permitted
|
1293 | 1304 | for a \grammarterm{template-parameter} declaration\iref{temp.param},
|
1294 | 1305 | the program is ill-formed.
|
1295 | 1306 |
|
1296 | 1307 | \pnum
|
1297 |
| -A |
1298 |
| -\grammarterm{template-argument} |
1299 |
| -for a non-type |
1300 |
| -\grammarterm{template-parameter} |
1301 |
| -shall be |
1302 |
| -a converted |
1303 |
| -constant expression\iref{expr.const} |
| 1308 | +A \grammarterm{template-argument} |
| 1309 | +for a non-type \grammarterm{template-parameter} |
| 1310 | +shall be a converted constant expression\iref{expr.const} |
1304 | 1311 | of the type of the \grammarterm{template-parameter}.
|
1305 | 1312 | For a non-type \grammarterm{template-parameter} of reference or pointer type,
|
1306 |
| -the value of the constant expression shall not refer to |
1307 |
| -(or for a pointer type, shall not be the address of): |
| 1313 | +or for each non-static data member of reference or pointer type |
| 1314 | +in a non-type \grammarterm{template-parameter} of class type or subobject thereof, |
| 1315 | +the reference or pointer value shall not refer to |
| 1316 | +or be the address of (respectively): |
1308 | 1317 |
|
1309 | 1318 | \begin{itemize}
|
1310 | 1319 | \item a subobject\iref{intro.object},
|
|
1353 | 1362 |
|
1354 | 1363 | \pnum
|
1355 | 1364 | \begin{note}
|
1356 |
| -A string literal\iref{lex.string} |
1357 |
| -is not an acceptable |
1358 |
| -\grammarterm{template-argument}. |
| 1365 | +A string literal\iref{lex.string} is |
| 1366 | +not an acceptable \grammarterm{template-argument} |
| 1367 | +for a \grammarterm{template-parameter} of non-class type. |
1359 | 1368 | \begin{example}
|
1360 | 1369 |
|
1361 | 1370 | \begin{codeblock}
|
1362 |
| -template<class T, const char* p> class X { |
| 1371 | +template<class T, T p> class X { |
1363 | 1372 | @\commentellip@
|
1364 | 1373 | };
|
1365 | 1374 |
|
1366 |
| -X<int, "Studebaker"> x1; // error: string literal as template-argument |
| 1375 | +X<const char*, "Studebaker"> x; // error: string literal as template-argument |
1367 | 1376 |
|
1368 | 1377 | const char p[] = "Vivisectionist";
|
1369 |
| -X<int,p> x2; // OK |
| 1378 | +X<const char*, p> y; // OK |
| 1379 | + |
| 1380 | +class A { |
| 1381 | + constexpr A(const char*) {} |
| 1382 | + auto operator<=>(A, A) = default; |
| 1383 | +}; |
| 1384 | + |
| 1385 | +X<A, "Pyrophoricity"> z; // OK, string literal is a constructor argument to \tcode{A} |
1370 | 1386 | \end{codeblock}
|
1371 | 1387 | \end{example}
|
1372 | 1388 | \end{note}
|
|
2013 | 2029 | refer to the same template and}
|
2014 | 2030 | \item {their corresponding type \grammarterm{template-argument}{s} are the
|
2015 | 2031 | same type and}
|
2016 |
| -\item {their corresponding non-type |
2017 |
| -template arguments of |
2018 |
| -integral or enumeration type have identical values and} |
2019 |
| -\item {their corresponding non-type \grammarterm{template-argument}{s} of |
2020 |
| -pointer type refer to the same object or function or are both the null |
2021 |
| -pointer value and} |
2022 | 2032 | \item {their corresponding non-type \grammarterm{template-argument}{s} of
|
2023 | 2033 | pointer-to-member type refer to the same class member or are both the null member
|
2024 | 2034 | pointer value and}
|
2025 | 2035 | \item {their corresponding non-type \grammarterm{template-argument}{s} of
|
2026 | 2036 | reference type refer to the same object or function and}
|
| 2037 | +\item {their remaining corresponding |
| 2038 | +non-type \grammarterm{template-argument}{s} |
| 2039 | +have the same type and value |
| 2040 | +after conversion to the type of the \grammarterm{template-parameter}, |
| 2041 | +where they are considered to have the same value if they compare equal |
| 2042 | +with \tcode{operator<=>}, and} |
2027 | 2043 | \item {their corresponding template \grammarterm{template-argument}{s} refer
|
2028 | 2044 | to the same template.}
|
2029 | 2045 | \end{itemize}
|
|
0 commit comments