Skip to content

Commit

Permalink
P2308R1 Template parameter initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
jensmaurer committed Nov 15, 2023
1 parent ecbeb5a commit b43de50
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 102 deletions.
5 changes: 2 additions & 3 deletions source/declarations.tex
Original file line number Diff line number Diff line change
Expand Up @@ -4026,9 +4026,7 @@
of a function declaration
or \grammarterm{lambda-declarator}
or in a
\grammarterm{template-parameter}\iref{temp.param};
in the latter case, the \grammarterm{initializer-clause} shall be an
\grammarterm{assignment-expression}.
\grammarterm{template-parameter}\iref{temp.param}.
A default argument shall not be specified for
a template parameter pack or
a function parameter pack.
Expand Down Expand Up @@ -5770,6 +5768,7 @@
\item in a \tcode{return} statement\iref{stmt.return}
\item as a \grammarterm{for-range-initializer}\iref{stmt.iter}
\item as a function argument\iref{expr.call}
\item as a template argument\iref{temp.arg.nontype}
\item as a subscript\iref{expr.sub}
\item as an argument to a constructor invocation\iref{dcl.init,expr.type.conv}
\item as an initializer for a non-static data member\iref{class.mem}
Expand Down
217 changes: 118 additions & 99 deletions source/templates.tex
Original file line number Diff line number Diff line change
Expand Up @@ -411,12 +411,11 @@
a non-type \grammarterm{template-parameter} of class type \tcode{T}
denotes a static storage duration object of type \tcode{const T},
known as a \defn{template parameter object},
whose value is that of the corresponding template argument
which is template-argument-equivalent\iref{temp.type} to
the corresponding template argument
after it has been converted
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}.
to the type of the \grammarterm{template-parameter}\iref{temp.arg.nontype}.
No two template parameter objects are template-argument-equivalent.
\begin{note}
If an \grammarterm{id-expression} names
a non-type non-reference \grammarterm{template-parameter},
Expand Down Expand Up @@ -483,40 +482,27 @@
for the invented type corresponding to the placeholder\iref{dcl.fct}.

\pnum
A
\defnx{default template-argument}{\idxgram{template-argument}!default}
is a
\grammarterm{template-argument}\iref{temp.arg} specified after
\tcode{=}
in a
\grammarterm{template-parameter}.
A default
\grammarterm{template-argument}
may be specified for any kind of
\grammarterm{template-parameter}
(type, non-type, template)
A \defnadj{default}{template argument} is
a template argument \iref{temp.arg} specified after \tcode{=}
in a \grammarterm{template-parameter}.
A default template argument may be specified for
any kind of \grammarterm{template-parameter} (type, non-type, template)
that is not a template parameter pack\iref{temp.variadic}.
A default
\grammarterm{template-argument}
may be specified in a template declaration.
A default
\grammarterm{template-argument}
shall not be specified in the
\grammarterm{template-parameter-list}{s}
of the definition of a member of a class template that appears outside
of the member's class.
A default
\grammarterm{template-argument}
A default template argument may be specified in a template declaration.
A default template argument shall not be specified in
the \grammarterm{template-parameter-list}{s}
of the definition of a member of a class template
that appears outside of the member's class.
A default template argument
shall not be specified in a friend class template declaration.
If a friend function template declaration $D$
specifies a default \grammarterm{template-argument},
specifies a default template argument,
that declaration shall be a definition and
there shall be no other declaration of the function template
which is reachable from $D$ or from which $D$ is reachable.

\pnum
The set of default
\grammarterm{template-argument}{s}
The set of default template arguments
available for use is obtained by merging the default arguments
from all prior declarations of the template in the
same way default function arguments are\iref{dcl.fct.default}.
Expand All @@ -532,29 +518,24 @@
\end{example}

\pnum
If a
\grammarterm{template-parameter}
of a class template, variable template, or alias template has a default
\grammarterm{template-argument},
each subsequent
\grammarterm{template-parameter}
shall either have a default
\grammarterm{template-argument}
supplied
or be a template parameter pack. If a \grammarterm{template-parameter}
of a primary class template, primary variable template, or alias template
is a template parameter pack, it shall be the last
\grammarterm{template-parameter}.
A template parameter pack of a function template shall not be followed by
another
template parameter unless that template parameter can be deduced from the
parameter-type-list\iref{dcl.fct} of the function template or has a
default argument\iref{temp.deduct}.
If a \grammarterm{template-parameter}
of a class template, variable template, or alias template has
a default template argument,
each subsequent \grammarterm{template-parameter}
shall either have a default template argument supplied or
be a template parameter pack.
If a \grammarterm{template-parameter} of
a primary class template, primary variable template, or alias template
is a template parameter pack,
it shall be the last \grammarterm{template-parameter}.
A template parameter pack of a function template
shall not be followed by another template parameter
unless that template parameter can be deduced from the
parameter-type-list\iref{dcl.fct} of the function template or
has a default argument\iref{temp.deduct}.
A template parameter of a deduction guide template\iref{temp.deduct.guide}
that does not have a default argument
shall be deducible
from the parameter-type-list
of the deduction guide template.
that does not have a default argument shall be deducible
from the parameter-type-list of the deduction guide template.
\begin{example}
\begin{codeblock}
template<class T1 = int, class T2> class B; // error
Expand All @@ -567,15 +548,10 @@

\indextext{\idxcode{<}!template and}%
\pnum
When parsing a
default
\grammarterm{template-argument}
for a non-type
\grammarterm{template-parameter},
the first non-nested
\tcode{>}
is taken as the end of the
\grammarterm{template-parameter-list}
When parsing a default template argument
for a non-type \grammarterm{template-parameter},
the first non-nested \tcode{>} is taken as
the end of the \grammarterm{template-parameter-list}
rather than a greater-than operator.
\begin{example}
\begin{codeblock}
Expand All @@ -588,16 +564,12 @@
\end{example}

\pnum
A
\grammarterm{template-parameter}
of a template
\grammarterm{template-parameter}
is permitted to have a default
\grammarterm{template-argument}.
When such default arguments are specified, they apply to the template
\grammarterm{template-parameter}
in the scope of the template
\grammarterm{template-parameter}.
A \grammarterm{template-parameter} of
a template \grammarterm{template-parameter}
is permitted to have a default template argument.
When such default arguments are specified,
they apply to the template \grammarterm{template-parameter}
in the scope of the template \grammarterm{template-parameter}.
\begin{example}
\begin{codeblock}
template <template <class TT = float> class T> struct A {
Expand Down Expand Up @@ -681,7 +653,8 @@
\nontermdef{template-argument}\br
constant-expression\br
type-id\br
id-expression
id-expression\br
braced-init-list
\end{bnf}

\pnum
Expand Down Expand Up @@ -1035,11 +1008,9 @@
X<Y::S> y; // error: \tcode{S} not accessible
\end{codeblock}
\end{example}
For a
\grammarterm{template-argument}
that is a class type or a class template, the template
definition has no special access rights to the
members of the \grammarterm{template-argument}.
For a template argument that is a class type or a class template,
the template definition has no special access rights
to the members of the template argument.
\begin{example}
\begin{codeblock}
template <template <class TT> class T> class A {
Expand All @@ -1056,11 +1027,8 @@
\end{example}

\pnum
When template argument packs or default
\grammarterm{template-argument}{s}
are used, a
\grammarterm{template-argument}
list can be empty.
When template argument packs or default template arguments are used,
a \grammarterm{template-argument} list can be empty.
In that case the empty
\tcode{<>}
brackets shall still be used as the
Expand Down Expand Up @@ -1093,8 +1061,7 @@
\end{example}

\pnum
If the use of a
\grammarterm{template-argument}
If the use of a template argument
gives rise to an ill-formed construct in the instantiation of a
template specialization, the program is ill-formed.

Expand Down Expand Up @@ -1176,23 +1143,60 @@
the type of the parameter is the type deduced
for the variable \tcode{x} in the invented declaration
\begin{codeblock}
T x = @\grammartermnc{template-argument}@ ;
T x = @$E$@ ;
\end{codeblock}
where $E$ is the template argument provided for the parameter.
\begin{note}
$E$ is a \grammarterm{template-argument} or
(for a default template argument) an \grammarterm{initializer-clause}.
\end{note}
If a deduced parameter type is not permitted
for a \grammarterm{template-parameter} declaration\iref{temp.param},
the program is ill-formed.

\pnum
A \grammarterm{template-argument}
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}
is an overload set
(or the address of such, including forming a pointer-to-member),
the matching function is selected from the set\iref{over.over}.
\end{note}
The value of a non-type \grammarterm{template-parameter} $P$
of (possibly deduced) type \tcode{T}
is determined from its template argument $A$ as follows.
If \tcode{T} is not a class type and
$A$ is not a \grammarterm{braced-init-list},
$A$ shall be a converted constant expression\iref{expr.const}
of type \tcode{T}; the value of $P$ is $A$ (as converted).

\pnum
Otherwise, a temporary variable
\begin{codeblock}
constexpr T v = @$A$@;
\end{codeblock}
is introduced.
The lifetime of \tcode{v} ends immediately after initializing it and
any template parameter object (see below).
For each such variable,
the \grammarterm{id-expression} \tcode{v}
is termed a \defn{candidate initializer}.

\pnum
If \tcode{T} is a class type,
a template parameter object\iref{temp.param} exists
that is constructed so as to be template-argument-equivalent to \tcode{v};
$P$ denotes that template parameter object.
$P$ is copy-initialized from an unspecified candidate initializer
that is template-argument-equivalent to \tcode{v}.
If, for the initialization from any candidate initializer,
\begin{itemize}
\item
the initialization would be ill-formed, or
\item
the full-expression of an invented \grammarterm{init-declarator}
for the initialization would not be a constant expression
when interpreted as a constant-expression\iref{expr.const}, or
\item
the initialization would cause $P$ to not be template-argument-equivalent\iref{temp.type} to \tcode{v},
\end{itemize}
the program is ill-formed.

\pnum
Otherwise, the value of $P$ is that of v.

\pnum
For a non-type \grammarterm{template-parameter} of reference or pointer type,
Expand Down Expand Up @@ -1236,6 +1240,21 @@
B<'a'> b2; // OK, template parameter type is \tcode{char}
B<2.5> b3; // OK, template parameter type is \tcode{double}
B<void(0)> b4; // error: template parameter type cannot be \keyword{void}

template<int i> struct C { /* ... */ };
C<{ 42 }> c1; // OK

struct J1 {
J1 *self = this;
};
B<J1{}> j1; // error: initialization of template parameter object is not a constant expression

struct J2 {
J2 *self = this;
constexpr J2() {}
constexpr J2(const J2&) {}
};
B<J2{}> j2; // error: template parameter object not template-argument-equivalent to introduced temporary
\end{codeblock}
\end{example}

Expand Down Expand Up @@ -2036,9 +2055,9 @@
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
the template parameter values determined by
their corresponding non-type template arguments\iref{temp.arg.nontype}
are template-argument-equivalent (see below), and

\item
their corresponding template \grammarterm{template-argument}{s}
Expand Down

0 comments on commit b43de50

Please sign in to comment.