CWG Issue 1111 (original) (raw)
This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 118e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2025-11-05
1111. Remove dual-scope lookup of member template names
Section: _N4868_.6.5.6 [basic.lookup.classref]Status: C++11Submitter: USDate: 2010-08-02
[Voted into the WP at the March, 2011 meeting.]
According 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 305fixed 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 a
nconversion-function-id is looked upboth 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 contextsin the same manner as a_conversion-type-id_ in a class member access (see _N4868_.6.5.6 [basic.lookup.classref]);
- a conversion-type-id of a
- 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, otherwiseif 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, otherwiseif 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 operator T(); }; }
int main() { N::A a; a.operator A(); // calls N::A::operator N::A }
—_end example_]