C++ Logo


Advanced search

Re: When is semantic correctness checked in a template?

From: Andrew Schepler <aschepler_at_[hidden]>
Date: Tue, 6 Apr 2021 23:31:51 -0400
On Tue, Apr 6, 2021 at 8:58 PM Myria via Std-Discussion <
std-discussion_at_[hidden]> wrote:

> When does a template's semantic correctness get checked (for
> non-dependent expressions)? If an identifier naming a type is used in
> a template in a way that is valid at template definition time, but the
> type of the identifier changes prior to instantiation, what happens?
> Note that this is not the case of name lookup changing, but rather the
> actual type of the identifier.
> In the following example, "a" starts out as "array of int of unknown
> bound" but becomes "array of int of bound 2" later in the program.
> Does "r" becoming bound to "a" become ill-formed for template
> instantiations that occur after "a" has its type change?
> extern int a[];
> template <int I>
> int t()
> {
> int (&r)[] = a; // important line
> return r[0] + I;
> }
> int f()
> {
> return t<4>();
> }
> int a[2];
> int g()
> {
> return t<5>(); // is t's "r" binding well-formed?
> }

I think [temp.res]/(8.5.1)
<https://timsong-cpp.github.io/cppwp/n4861/temp.res#8.5.1> applies to both
t<4> and t<5>, making both ill-formed, no diagnostic required.

> The validity of a template may be checked prior to any instantiation. The
> program is ill-formed, no diagnostic required, if:
> - ..., or
> - a hypothetical instantiation of a template immediately following its
> definition would be ill-formed due to a construct that does not depend on a
> template parameter, or
> - the interpretation of such a construct in the hypothetical
> instantiation is different from the interpretation of the corresponding
> construct in any actual instantiation of the template. [ *Note:* This
> can happen in situations including the following:
> - a type used in a non-dependent name is incomplete at the point at
> which a template is defined but is complete at the point at which an
> instantiation is performed, or ...
So the t<5> in g is a problem in just the way described, since the
interpretation in the hypothetical instantiation is well-formed because of
use of the incomplete type int[], but the interpretation in the actual
instantiation is ill-formed because of use of the complete type int[2].

And the t<4> in f is also a problem, because [temp.point]/7
<https://timsong-cpp.github.io/cppwp/n4861/temp.point#7> says the function
template specialization has an additional point of instantiation at the end
of the translation unit (since C++20 modules are not involved here).
[temp.res]/(8.5) applies if any instantiation differs from the hypothetical
immediate instantiation, so even though the point of instantiation
immediately after the definition of f is okay, the additional point of
instantiation at the end makes the program ill-formed.

-- Andrew Schepler

Received on 2021-04-06 22:32:06