Doc. No.: | WG21/N1490, J16/03-0073 |
---|---|
Date: | 2003-09-08 |
Reply to: | Clark Nelson |
Phone: | +1-503-712-8433 |
Email: | clark.nelson@intel.com |
It turns out that issue 301 is a duplicate of issue 38, which was resolved in the TC. I am reassured by the fact that I independently came up with the same grammar change that Jamie Schmeiser did. For reference, here is that grammar change (from §13.5):
- operator-function-id:
operator
operatoroperator
operator<
template-argument-listopt>
However, when I looked at the matter carefully, I discovered that there are many changes that need to be made to resolve the issue, which were not made as part of issue 38. Moreover, for the sake of those changes, and to have a convenient term for an important concept, the grammar needs to be tweaked a bit.
In several places, there are restrictions or conditions on "being a template-id". Of course an operator-function-id with a template-argument-list isn't a template-id, but where those restrictions and conditions apply to function templates, it shouldn't matter whether the function has a name or an operator-function-id. My first thought was to refer instead to the presence of a template-argument-list, but of course that's optional. The restrictions and conditions are really syntactic, and actually refer to the presence of the angle brackets delimiting the template-argument-list, if present. So I propose to add a new production to refer to the delimited (optional) template-argument-list:
- operator-function-id:
operator
operatoroperator
operator template-argument-clause
- template-id:
- template-name template-argument-clause
- template-argument-clause:
<
template-argument-listopt>
The other necessary changes have to do with some consequences of the grammar changes:
<
is to be parsed as introducing a template-argument-clause,
or as being a relational operator (in other words, how to resolve the shift-reduce
conflict).The smallest possible addition would be in §13.5¶1:
A function declaration having one of the following operator-function-ids as its name declares an operator function. A function template declaration having one of the following operator-function-ids as its name declares an operator function template. A specialization of an operator function template is also an operator function. An operator function is said to implement the operator named in its operator-function-id.
If any other change were necessary, then it would certainly be necessary to modify §13.5¶6, which describes operator functions. However, it is at least conceivable that the above change would imply everything else that is true of operator function templates. But even if so, it may be desirable to be a little more explicit.
For template names, this is currently addressed in the first sentence of §14.2¶3:
After name lookup (3.4) finds that a name is a template-name, if this name is followed by a
<
, the<
is always taken as the beginning of a template-argument-list and never as a name followed by the less-than operator.
This description seems to be adequate for names of class templates. As far as
I can tell, the only ambiguity it resolves is from something that starts with
new X <
, in the scope of a class template X
. But even
without the grammar change, it was inadequate for names of function templates.
Probably after an identifier I, <
should always be interpreted
as introducing a template-argument-clause if any member of the overload
set identified by I is a function template. After all, function pointers
are very rarely compared for ordering, and it's not clear what other rule might
be workable.
My proposed revision of §14.2¶3:
After name lookup (3.4) finds that a name is a template-name, or refers to a set of overloaded functions any member of which is a function template, if this name is followed by a
<
, the<
is always taken as the beginning of a template-argument-clause and never asa name followed bythe less-than operator.
Clearly, this change is technically unrelated to operator functions. But it still seems to be necessary.
Getting back to operator function templates, I propose to add the following to §13.5¶1, between the grammar rules and the note:
If any member of the set of overloaded operator functions implementing the operator is a template, any immediately following
<
is interpreted as introducing a template-argument-clause, and not as a less-than operator.
There are several places where template-id is mentioned as the context in which a template-argument or template-argument-list may appear. Since that is no longer the only such context, these references are superfluous and should be deleted.
In a
friend
declaration naming a member function, a name used in the function declarator and not part of a template-argumentin a template-idis first looked up in the scope of the member function's class. If it is not found, or if the name is part of a template-argumentin a template-id, the look up is as described for unqualified names in the definition of the class granting friendship.
thetemplate-argumentsof a template-idare looked up in the context in which the entire postfix-expression occurs.
Note: I think that this sentence could also stand to be editorially improved. In the first place, a template-argument may be an expression containing an arbitrary number of names, and of course only names are looked up. Also, I don't understand why we're talking about a postfix-expression here. Here's how I think it should really read, without markup:
names in a template-argument are looked up in the context in which the containing id-expression occurs.
If the nested-name-specifier of a qualified-id nominates a namespace, the name specified after the nested-name-specifier is looked up in the scope of the namespace, except that
the template-argumentsnames in a template-argumentof a template-idare looked up in the context in which theentire postfix-expressioncontaining id-expression occurs.
The type and form of each template-argument
specified in a template-idshall match the type and form specified for the corresponding parameter declared by the template in its template-parameter-list.
Most of these changes are substantially replacing a reference to template-id with a reference to template-argument-clause.
When looking for a prior declaration of a class or a function declared as a
friend
, and when the name of thefriend
class or functionis neither a qualified name nor a template-idhas neither a nested-name-specifier nor a template-argument-clause, scopes outside the innermost enclosing namespace scope are not considered.
After I came up with this formulation, I realized that it assumes the resolution of core issue 355. Here's a formulation without that dependency:
When looking for a prior declaration of a class or a function declared as a
friend
, and when the name of thefriend
class or function is not a qualified name and does not have a template-argument-clause, scopes outside the innermost enclosing namespace scope are not considered.
A using-declaration shall not name a template-id.The unqualified-id in a using-declaration shall not include a template-argument-clause.
In a function template declaration, the declarator-id shall
be a template-name (i.e., not a template-id)not include a template-argument-clause.
A template specialization (14.7) can be referred to by a template-id or by an operator-function-id with a template-argument-clause:
When parsing a
template-idtemplate-argument-clause, the first non-nested>
127) is taken as the end of the template-argument-clause rather than a greater-than operator.
Note that the first sentence of this paragraph was modified above (under "The shift-reduce conflict").
When the template in a template-id is an overloaded function template,When the identifier in a template-id refers to a set of overloaded functions, or an operator-function-id contains a template-argument-clause, both non-template functions in the overload set and function templates in the overload set for which the template-arguments do not match the template-parameters are ignored.
the address of an object or function with external linkage,
including function templates and function template-ids but excluding non-static class members,expressed as&
id-expression where the&
is optional if the name refers to a function or array, or if the corresponding template-parameter is a reference; or
As far as I can tell, the text I'm recommending to delete makes no normative difference. In any event, non-static class data member names do not have external linkage, so there is no point in specifically excluding them here. Taken on the face of it, the exclusion could also be referring to non-static class member functions, but that's clearly not the intention. As far as the inclusion is concerned, I don't think that's meant to include non-member function templates with internal linkage (see §14¶4). So the inclusion seems to be intended only to clarify -- exactly what, I can't tell.
On the other hand, if that text really does perform some necessary function, it would probably be improved by replacing "template-ids" with "template specializations".
Two template-ids or operator-function-ids with template-argument-clauses refer to the same class or function if their
templatenames areidenticalthe same (clause 3), they refer to the same template, ....
The reference is more specifically to §3¶7.
A
template-id, that is, the template-name followed by a template-argument-listtemplate-argument-clause shall not be specified in the declaration of a primary template declaration.
if the name of the friend
is a qualified or unqualified template-idincludes a template-argument-clause, the friend declaration refers to a specialization of a function template, otherwise
A friend function declaration that is not a template declaration and in which the name of the friend is an unqualified
template-idname with a template-argument-clause shall refer to a specialization of a function template declared in the nearest enclosing namespace scope.
This could be formulated differently (better, in my opinion) if core issue 355 were resolved.
For a function call that depends on a template parameter, if the function name is an unqualified-id
but not a template-idand has no template-argument-clause, the candidate functions are found using the usual lookup rules (3.4.1, 3.4.2) except that:
In an explicit specialization declaration for a class template, a member of a class template or a class member template, the name of the class that is explicitly specialized shall be a template-id. In the explicit specialization declaration for a function template or a member function template, the name of the function or member function explicitly specialized may
be a template-idhave a template-argument-clause.
If the explicit instantiation is for a class, a function or a member template specialization, the unqualified-id in the declaration shall
be either a template-id or, wherehave a template-argument-clause, unless all template arguments can be deduced, a template-name.
A trailing template-argument can be left unspecified in the
template-id namingtemplate-argument-clause associated with the name of an explicit function template specialization provided it can be deduced from the function argument type.