This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-10-26
[Voted into the WP at the March, 2011 meeting.]
N3092 comment US 23According to _N4868_.6.5.6 [basic.lookup.classref] paragraph 1,
In a class member access expression (7.6.1.5 [expr.ref]), if the . or -> token is immediately followed by an identifier followed by a <, the identifier must be looked up to determine whether the < is the beginning of a template argument list (13.3 [temp.names]) or a less-than operator. The identifier is first looked up in the class of the object expression. If the identifier is not found, it is then looked up in the context of the entire postfix-expression and shall name a class template. If the lookup in the class of the object expression finds a template, the name is also looked up in the context of the entire postfix-expression and
if the name is not found, the name found in the class of the object expression is used, otherwise
if the name is found in the context of the entire postfix-expression and does not name a class template, the name found in the class of the object expression is used, otherwise
if the name found is a class template, it shall refer to the same entity as the one found in the class of the object expression, otherwise the program is ill-formed.
This makes the following ill-formed:
#include <set> using std::set; struct X { template <typename T> void set(const T& value); }; void foo() { X x; x.set<double>(3.2); }
That's confusing and unnecessary. The compiler has already done the lookup in X's scope, and the obviously-correct resolution is that one, not the identifier from the postfix-expression's scope. Issue 305 fixed a similar issue for destructor names but missed member functions.
Suggested resolution: Delete the end of paragraph 1, starting with “If the lookup in the class...” and including all three bullets.
Proposed resolution (November, 2010):
Change 6.5.5.2 [class.qual] bullet 1.2 as follows:
a conversion-type-id of an
conversion-function-id is looked up both in the scope of
the class and in the context in which the entire
postfix-expression occurs and shall refer to the same type in
both contexts in the same manner as a
conversion-type-id in a class member access (see _N4868_.6.5.6 [basic.lookup.classref]);
Change _N4868_.6.5.6 [basic.lookup.classref] paragraph 1 as follows:
In a class member access expression (7.6.1.5 [expr.ref]), if the . or -> token is immediately followed by an identifier followed by a <, the identifier must be looked up to determine whether the < is the beginning of a template argument list (13.3 [temp.names]) or a less-than operator. The identifier is first looked up in the class of the object expression. If the identifier is not found, it is then looked up in the context of the entire postfix-expression and shall name a class template.
If the lookup in the class of the object expression finds a template, the name is also looked up in the context of the entire postfix-expression and
if the name is not found, the name found in the class of the object expression is used, otherwise
if the name is found in the context of the entire postfix-expression and does not name a class template, the name found in the class of the object expression is used, otherwise
if the name found is a class template, it shall refer to the same entity as the one found in the class of the object expression, otherwise the program is ill-formed.
Change _N4868_.6.5.6 [basic.lookup.classref] paragraph 4 as follows:
If the id-expression in a class member access is a qualified-id of the form
class-name-or-namespace-name::...the class-name-or-namespace-name following the . or -> operator is
looked up both in the context of the entire postfix-expression and in the scope of the class of the object expression. If the name is found only in the scope of the class of the object expression, the name shall refer to a class-name. If the name is found only in the context of the entire postfix-expression, the name shall refer to a class-name or namespace-name. If the name is found in both contexts, the class-name-or-namespace-name shall refer to the same entity.first looked up in the class of the object expression and the name, if found, is used. Otherwise it is looked up in the context of the entire postfix-expression. [Note: See 6.5.5 [basic.lookup.qual], which describes the lookup of a name before ::, which will only find a type or namespace name. —end note]
Change _N4868_.6.5.6 [basic.lookup.classref] paragraph 7 as follows:
If the id-expression is a conversion-function-id, its conversion-type-id
shall denote the same type in both the context in which the entire postfix-expression occurs and in the context of the class of the object expression (or the class pointed to by the pointer expression).is first looked up in the class of the object expression and the name, if found and denotes a type, is used. Otherwise it is looked up in the context of the entire postfix-expression and the name shall denote a type. [Example:struct A { }; namespace N { struct A { void g() { } template <class T> operator T(); }; } int main() { N::A a; a.operator A(); // calls N::A::operator N::A }
—end example]