Skip to content

Commit 8f02007

Browse files
committed
P2662R3 Pack Indexing
1 parent 38dfe3d commit 8f02007

File tree

7 files changed

+145
-20
lines changed

7 files changed

+145
-20
lines changed

source/basic.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2170,7 +2170,7 @@
21702170
followed by a \tcode{::} scope resolution operator
21712171
considers only
21722172
namespaces, types, and templates whose specializations are types.
2173-
If a name, \grammarterm{template-id}, or \grammarterm{decltype-specifier}
2173+
If a name, \grammarterm{template-id}, or \grammarterm{computed-type-specifier}
21742174
is followed by a \tcode{::},
21752175
it shall designate a namespace, class, enumeration, or dependent type,
21762176
and the \tcode{::} is never interpreted as

source/classes.tex

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2188,7 +2188,7 @@
21882188
In an explicit destructor call, the destructor is specified by a
21892189
\tcode{\~{}}
21902190
followed by a
2191-
\grammarterm{type-name} or \grammarterm{decltype-specifier}
2191+
\grammarterm{type-name} or \grammarterm{computed-type-specifier}
21922192
that denotes the destructor's class type.
21932193
The invocation of a destructor is subject to the usual rules for member
21942194
functions\iref{class.mfct};
@@ -3397,16 +3397,16 @@
33973397

33983398
\begin{bnf}
33993399
\nontermdef{base-specifier}\br
3400-
\opt{attribute-specifier-seq} class-or-decltype\br
3401-
\opt{attribute-specifier-seq} \keyword{virtual} \opt{access-specifier} class-or-decltype\br
3402-
\opt{attribute-specifier-seq} access-specifier \opt{\keyword{virtual}} class-or-decltype
3400+
\opt{attribute-specifier-seq} class-or-computed-type-specifier\br
3401+
\opt{attribute-specifier-seq} \keyword{virtual} \opt{access-specifier} class-or-computed-type-specifier\br
3402+
\opt{attribute-specifier-seq} access-specifier \opt{\keyword{virtual}} class-or-computed-type-specifier
34033403
\end{bnf}
34043404

34053405
\begin{bnf}
3406-
\nontermdef{class-or-decltype}\br
3406+
\nontermdef{class-or-computed-type-specifier}\br
34073407
\opt{nested-name-specifier} type-name\br
34083408
nested-name-specifier \keyword{template} simple-template-id\br
3409-
decltype-specifier
3409+
computed-type-specifier
34103410
\end{bnf}
34113411

34123412
\indextext{specifier access|see{access specifier}}%

source/compatibility.tex

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,29 @@
3131
bool b = ne({2,3}, {1,2,3}); // unspecified result; previously \tcode{false}
3232
\end{codeblock}
3333

34+
\rSec2[diff.cpp23.dcl.dcl]{\ref{dcl.dcl}: Declarations}
35+
36+
\diffref{decl.array}
37+
\change
38+
Previously, \tcode{T...[n]} would declare a pack of function parameters.
39+
\tcode{T...[n]} is now a \grammarterm{pack-index-specifier}.
40+
\rationale
41+
Improve the handling of packs.
42+
\effect
43+
Valid \CppXXIII{} code that declares a pack of parameters
44+
without specifying a \grammarterm{declarator-id} becomes ill-formed.
45+
For example:
46+
\begin{codeblock}
47+
template <typename... T>
48+
void f(T... [1]);
49+
template <typename... T>
50+
void g(T... ptr[1]);
51+
int main() {
52+
f<int, double>(nullptr, nullptr); // ill-formed, previously \tcode{void f<int, double>(int [1], double [1])}
53+
g<int, double>(nullptr, nullptr); // ok
54+
}
55+
\end{codeblock}
56+
3457
\rSec2[diff.cpp23.strings]{\ref{strings}: strings library}
3558

3659
\diffref{string.conversions}

source/declarations.tex

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,7 +1285,7 @@
12851285
\nontermdef{simple-type-specifier}\br
12861286
\opt{nested-name-specifier} type-name\br
12871287
nested-name-specifier \keyword{template} simple-template-id\br
1288-
decltype-specifier\br
1288+
computed-type-specifier\br
12891289
placeholder-type-specifier\br
12901290
\opt{nested-name-specifier} template-name\br
12911291
\keyword{char}\br
@@ -1311,6 +1311,12 @@
13111311
typedef-name
13121312
\end{bnf}
13131313

1314+
\begin{bnf}
1315+
\nontermdef{computed-type-specifier}\br
1316+
decltype-specifier\br
1317+
pack-index-specifier
1318+
\end{bnf}
1319+
13141320
\pnum
13151321
\indextext{component name}
13161322
The component names of a \grammarterm{simple-type-specifier} are those of its
@@ -1382,6 +1388,7 @@
13821388
\grammarterm{type-name} & the type named \\
13831389
\grammarterm{simple-template-id} & the type as defined in~\ref{temp.names}\\
13841390
\grammarterm{decltype-specifier} & the type as defined in~\ref{dcl.type.decltype}\\
1391+
\grammarterm{pack-index-specifier} & the type as defined in~\ref{dcl.type.pack.index}\\
13851392
\grammarterm{placeholder-type-specifier}
13861393
& the type as defined in~\ref{dcl.spec.auto}\\
13871394
\grammarterm{template-name} & the type as defined in~\ref{dcl.type.class.deduct}\\
@@ -1431,6 +1438,32 @@
14311438
forces \tcode{char} objects to be signed; it is redundant in other contexts.
14321439
\end{note}
14331440

1441+
\rSec3[dcl.type.pack.index]{Pack indexing specifier}
1442+
1443+
\begin{bnf}
1444+
\nontermdef{pack-index-specifier}\br
1445+
typedef-name \terminal{...} \terminal{[} constant-expression \terminal{]}
1446+
\end{bnf}
1447+
1448+
\pnum
1449+
The \grammarterm{typedef-name} $P$ in a \grammarterm{pack-index-specifier}
1450+
shall denote a pack.
1451+
1452+
\pnum
1453+
The \grammarterm{constant-expression} shall be
1454+
a converted constant expression\iref{expr.const} of type \tcode{std::size_t}
1455+
whose value $V$, termed the index,
1456+
is such that $0 \le V < \tcode{sizeof...(}P\tcode{)}$.
1457+
1458+
\pnum
1459+
A \grammarterm{pack-index-specifier} is a pack expansion\iref{temp.variadic}.
1460+
1461+
\pnum
1462+
\begin{note}
1463+
The \grammarterm{pack-index-specifier} denotes
1464+
the type of the $V^\tcode{th}$ element of the pack\iref{temp.variadic}.
1465+
\end{note}
1466+
14341467
\rSec3[dcl.type.elab]{Elaborated type specifiers}%
14351468
\indextext{type specifier!elaborated}%
14361469
\indextext{\idxcode{typename}}%
@@ -1604,6 +1637,13 @@
16041637
decltype(i) x2; // type is \tcode{int}
16051638
decltype(a->x) x3; // type is \tcode{double}
16061639
decltype((a->x)) x4 = x3; // type is \tcode{const double\&}
1640+
1641+
void f() {
1642+
[](auto ...pack) {
1643+
decltype(pack...[0]) x5; // type is \tcode{int}
1644+
decltype((pack...[0])) x6; // type is \tcode{int\&}
1645+
}(0);
1646+
}
16071647
\end{codeblock}
16081648
\end{example}
16091649
\begin{note}
@@ -2366,7 +2406,6 @@
23662406
\begin{bnf}
23672407
\nontermdef{noptr-abstract-pack-declarator}\br
23682408
noptr-abstract-pack-declarator parameters-and-qualifiers\br
2369-
noptr-abstract-pack-declarator \terminal{[} \opt{constant-expression} \terminal{]} \opt{attribute-specifier-seq}\br
23702409
\terminal{...}
23712410
\end{bnf}
23722411

source/expressions.tex

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,7 +1325,8 @@
13251325
\begin{bnf}
13261326
\nontermdef{id-expression}\br
13271327
unqualified-id\br
1328-
qualified-id
1328+
qualified-id\br
1329+
pack-index-expression
13291330
\end{bnf}
13301331

13311332
\pnum
@@ -1430,7 +1431,7 @@
14301431
conversion-function-id\br
14311432
literal-operator-id\br
14321433
\terminal{\~} type-name\br
1433-
\terminal{\~} decltype-specifier\br
1434+
\terminal{\~} computed-type-specifier\br
14341435
template-id
14351436
\end{bnf}
14361437

@@ -1447,7 +1448,7 @@
14471448
\grammarterm{conversion-function-id}{s}, see~\ref{class.conv.fct}; for
14481449
\grammarterm{literal-operator-id}{s}, see~\ref{over.literal}; for
14491450
\grammarterm{template-id}{s}, see~\ref{temp.names}.
1450-
A \grammarterm{type-name} or \grammarterm{decltype-specifier}
1451+
A \grammarterm{type-name} or \grammarterm{computed-type-specifier}
14511452
prefixed by \tcode{\~} denotes the destructor of the type so named;
14521453
see~\ref{expr.prim.id.dtor}.
14531454
Within the definition of a non-static member function, an
@@ -1595,7 +1596,7 @@
15951596
\terminal{::}\br
15961597
type-name \terminal{::}\br
15971598
namespace-name \terminal{::}\br
1598-
decltype-specifier \terminal{::}\br
1599+
computed-type-specifier \terminal{::}\br
15991600
nested-name-specifier identifier \terminal{::}\br
16001601
nested-name-specifier \opt{\keyword{template}} simple-template-id \terminal{::}
16011602
\end{bnf}
@@ -1633,8 +1634,8 @@
16331634
\pnum
16341635
The \grammarterm{nested-name-specifier} \tcode{::} nominates
16351636
the global namespace.
1636-
A \grammarterm{nested-name-specifier} with a \grammarterm{decltype-specifier}
1637-
nominates the type denoted by the \grammarterm{decltype-specifier},
1637+
A \grammarterm{nested-name-specifier} with a \grammarterm{computed-type-specifier}
1638+
nominates the type denoted by the \grammarterm{computed-type-specifier},
16381639
which shall be a class or enumeration type.
16391640
If a \grammarterm{nested-name-specifier} $N$
16401641
is declarative and
@@ -1666,9 +1667,9 @@
16661667
\pnum
16671668
A \grammarterm{qualified-id} shall not be of the form
16681669
\grammarterm{nested-name-specifier} \opt{\keyword{template}} \tcode{\~}
1669-
\grammarterm{decltype-specifier}
1670+
\grammarterm{computed-type-specifier}
16701671
nor of the form
1671-
\grammarterm{decltype-specifier} \tcode{::} \tcode{\~} \grammarterm{type-name}.
1672+
\grammarterm{computed-type-specifier} \tcode{::} \tcode{\~} \grammarterm{type-name}.
16721673

16731674
\pnum
16741675
The result of a \grammarterm{qualified-id} $Q$ is
@@ -1690,6 +1691,32 @@
16901691
\end{itemize}
16911692
and a prvalue otherwise.
16921693

1694+
\rSec3[expr.prim.pack.index]{Pack indexing expression}
1695+
1696+
\begin{bnf}
1697+
\nontermdef{pack-index-expression}\br
1698+
id-expression \terminal{...} \terminal{[} constant-expression \terminal{]}
1699+
\end{bnf}
1700+
1701+
\pnum
1702+
The \grammarterm{id-expression} $P$ in a \grammarterm{pack-index-expression}
1703+
shall be an \grammarterm{identifier} that denotes a pack.
1704+
1705+
\pnum
1706+
The \grammarterm{constant-expression} shall be
1707+
a converted constant expression\iref{expr.const} of type \tcode{std::size_t}
1708+
whose value $V$, termed the index,
1709+
is such that $0 \le V < \tcode{sizeof...(}P\tcode{)}$.
1710+
1711+
\pnum
1712+
A \grammarterm{pack-index-expression} is a pack expansion\iref{temp.variadic}.
1713+
1714+
\pnum
1715+
\begin{note}
1716+
A \grammarterm{pack-index-expression} denotes
1717+
the $V^\tcode{th}$ element of the pack\iref{temp.variadic}.
1718+
\end{note}
1719+
16931720
\rSec3[expr.prim.id.dtor]{Destruction}
16941721

16951722
\pnum
@@ -4689,14 +4716,14 @@
46894716
\end{note}
46904717
There is an ambiguity
46914718
in the grammar when \tcode{\~{}} is followed by
4692-
a \grammarterm{type-name} or \grammarterm{decltype-specifier}.
4719+
a \grammarterm{type-name} or \grammarterm{computed-type-specifier}.
46934720
The ambiguity is resolved by treating \tcode{\~{}} as the
46944721
operator rather than as the start of an \grammarterm{unqualified-id}
46954722
naming a destructor.
46964723
\begin{note}
46974724
Because the grammar does not permit an operator to follow the
46984725
\tcode{.}, \tcode{->}, or \tcode{::} tokens, a \tcode{\~{}} followed by
4699-
a \grammarterm{type-name} or \grammarterm{decltype-specifier} in a
4726+
a \grammarterm{type-name} or \grammarterm{computed-type-specifier} in a
47004727
member access expression or \grammarterm{qualified-id} is
47014728
unambiguously parsed as a destructor name.
47024729
\end{note}

source/preprocessor.tex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1851,6 +1851,7 @@
18511851
\defnxname{cpp_nontype_template_args} & \tcode{201911L} \\ \rowsep
18521852
\defnxname{cpp_nontype_template_parameter_auto} & \tcode{201606L} \\ \rowsep
18531853
\defnxname{cpp_nsdmi} & \tcode{200809L} \\ \rowsep
1854+
\defnxname{cpp_pack_indexing} & \tcode{202311L} \\ \rowsep
18541855
\defnxname{cpp_placeholder_variables} & \tcode{202306L} \\ \rowsep
18551856
\defnxname{cpp_range_based_for} & \tcode{202211L} \\ \rowsep
18561857
\defnxname{cpp_raw_strings} & \tcode{200710L} \\ \rowsep

source/templates.tex

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2144,6 +2144,19 @@
21442144
e.g., by a \grammarterm{typedef-name}.
21452145
\end{note}
21462146

2147+
\pnum
2148+
For a type template parameter pack \tcode{T},
2149+
\tcode{T...[}\grammarterm{constant-expression}\tcode{]} denotes
2150+
a unique dependent type.
2151+
2152+
\pnum
2153+
If the \grammarterm{constant-expression} of a \grammarterm{pack-index-specifier}
2154+
is value-dependent,
2155+
two such \grammarterm{pack-index-specifier}s refer to the same type
2156+
only if their \grammarterm{constant-expression}s are equivalent\iref{temp.over.link}.
2157+
Otherwise, two such \grammarterm{pack-index-specifier}s refer to the same type
2158+
only if their indexes have the same value.
2159+
21472160
\rSec1[temp.decls]{Template declarations}
21482161

21492162
\rSec2[temp.decls.general]{General}
@@ -2743,6 +2756,12 @@
27432756
\item In a \tcode{sizeof...} expression\iref{expr.sizeof}; the pattern is an
27442757
\grammarterm{identifier}.
27452758

2759+
\item In a \grammarterm{pack-index-expression};
2760+
the pattern is an \grammarterm{identifier}.
2761+
2762+
\item In a \grammarterm{pack-index-spexifier};
2763+
the pattern is a \grammarterm{typedef-name}.
2764+
27462765
\item In a \grammarterm{fold-expression}\iref{expr.prim.fold};
27472766
the pattern is the \grammarterm{cast-expression}
27482767
that contains an unexpanded pack.
@@ -2845,6 +2864,16 @@
28452864
The instantiation of a \tcode{sizeof...} expression\iref{expr.sizeof} produces
28462865
an integral constant with value $N$.
28472866

2867+
\pnum
2868+
When instantiating a \grammarterm{pack-index-expression} $P$,
2869+
let $K$ be the index of $P$.
2870+
The instantiation of P is the \grammarterm{id-expression} $E_K$.
2871+
2872+
\pnum
2873+
When instantiating a \grammarterm{pack-index-specifier} $P$,
2874+
let $K$ be the index of $P$.
2875+
The instantiation of P is the \grammarterm{typedef-name} $E_K$.
2876+
28482877
\pnum
28492878
The instantiation of an \grammarterm{alignment-specifier} with an ellipsis
28502879
produces $\tcode{E}_1$ $\tcode{E}_2$ $\dotsc$ $\tcode{E}_N$.
@@ -5046,7 +5075,7 @@
50465075
This includes an injected-class-name\iref{class.pre} of a class template
50475076
used without a \grammarterm{template-argument-list}.
50485077
\end{footnote}
5049-
or
5078+
\item a \grammarterm{pack-index-specifier}, or
50505079
\item denoted by \tcode{decltype(}\grammarterm{expression}{}\tcode{)},
50515080
where \grammarterm{expression} is type-dependent\iref{temp.dep.expr}.
50525081
\end{itemize}
@@ -5193,6 +5222,10 @@
51935222
\pnum
51945223
A \grammarterm{fold-expression} is type-dependent.
51955224

5225+
\pnum
5226+
A \grammarterm{pack-index-expression} is type-dependent
5227+
if its \grammarterm{id-expression} is type-dependent.
5228+
51965229
\rSec3[temp.dep.constexpr]{Value-dependent expressions}
51975230

51985231
\pnum
@@ -8132,6 +8165,8 @@
81328165
of a type that was specified using a
81338166
\grammarterm{qualified-id}.
81348167
\item
8168+
A \grammarterm{pack-index-specifier} or a \grammarterm{pack-index-expression}.
8169+
\item
81358170
The \grammarterm{expression} of a \grammarterm{decltype-specifier}.
81368171
\item
81378172
A non-type template argument or an array bound in which a subexpression

0 commit comments

Comments
 (0)