Topic: Comment on DR'd issue 206
Author: jthill_@mac.com (Jim Hill)
Date: Tue, 11 Dec 2001 16:00:20 GMT Raw View
Core language issue 206 asks:
>>>
At what point are semantic constraints applied to uses of
non-dependent names in template definitions? According to 14.6.3
[temp.nondep], such names are looked up and bound at the point at
which they are used, i.e., the point of definition and not the point
of instantiation. However, the text does not mention the checking of
semantic constraints.
<<<
and the proposed resolution is to declare usage like
struct S; template<typename> struct T { S s; }; struct S { };
undefined behavior.
I believe this would introduce a self-contradiction into the standard,
and that the issue should be reopened (to be closed as NAD, or to add
a note (to, say, 14.6.3) clarifying that templates are not types or
functions or objects, and have their own constraints.
In an email discussion about whether the example usage was incorrect,
John Spicer mentioned
f(p->x);
as an example of usage that the Standard says can be fully analyzed at
template definition (or at least independently of instantiation - I'm
paraphrasing) if none of the names is dependent.
I think that's true, but irrelevant to the situation from the DR.
Consider 14.6p9 in this context:
struct P; void f(int),f(char*);
template<class> struct U { U(P *p) { f(p->x); } };
template<class> struct V { V(P p} { f(p); } };
I think U is an ill-formed template, and V is valid.
The names (all non-dependent) that need binding are f, P and x.
14.6p9, for reference:
| If a name does not depend on a template parameter (as defined in
| 14.6.2), a declaration (or set of declarations) for that name
| shall be in scope at the point where the name appears in the
| template definition; the name is bound to the declaration (or
| declarations) found at that point and this binding is not
| affected by declarations that are visible at the point of
| instantiation.
It clearly applies here.
For template U, there's no declaration in scope for [P::]`x`, and no
later declaration can amend that, so the template violates the
constraint. That's easy.
For template V, both f and P have declarations in scope. P has of
course only one; f has two, both of which are in the candidate set for
overload resolution. The complete declaration of P may declare
conversion operators that can match `int` or `char *`, so a valid
instantiation is possible; f is bound to (the set of) both
declarations.
If overload resolution were required to be possible given only the
declarations so far, the compiler could resolve `f` to a single
declaration and there would be no need to mention "sets" of
declarations. So overload resolution is not necessarily possible here
- but that can only be the case when the types possible for f's
argument can't be determined - and that's only possible if P's type is
incomplete.
So incomplete types are allowed in template definitions, and
struct S; template<class> struct V {S s;};
struct S{}; template struct V<int>;
violates no template or class constraints.
[end payload, begin minor points and such]
So the answer to issue 206 should be that definition constraints are
checked when the definition is encountered, and as pointed out by
14.6p7, for templates, it may be may be possible to diagnose
constraints that will be violated by all possible instantiations; and
that the standard permits those conditions to be diagnosed given only
the template. Of course templates have their own constraints. [I
actually think that the constraints for non-dependent names are too
tight; that an incomplete (but determinate) declaration of an
enclosing class should be permissible, but that's just as NAD as issue
206.]
But changing the Standard to render the currently-valid examples here
undefined is a radical change that pointlessly tangles the meaning of
templates with that of types and functions, which are entirely
different concepts.
And the fact that the proposed resolution contradicts 14p9, which
answers the question raised by this issue, shows it was not
sufficiently well-considered.
Jim
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: jthill_@mac.com (Jim Hill)
Date: Tue, 11 Dec 2001 17:34:47 GMT Raw View
I apologize for following my own. A correction and an amendment:
`14p9` at the end was of course intended to be `14.6p9`, and there's
non-normative language that states rather than implies the presumption
in 14.6p7: "[Note: if a template is instantiated, errors will be
diagnosed according to the _other_ rules in this Standard. ..."
[emphasis mine].
Jim
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]