Title
Remove dual-scope lookup of member template names
Status
c++11
Section
_N4868_.6.5.6 [basic.lookup.classref]
Submitter
US

Created on 2010-08-02.00:00:00 last changed 96 months ago

Messages

Date: 2011-03-15.00:00:00

[Voted into the WP at the March, 2011 meeting.]

Date: 2010-11-15.00:00:00

Proposed resolution (November, 2010):

  1. Change 6.5.5.2 [class.qual] paragraph 1 bullet 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]);

  2. Change _N4868_.6.5.6 [basic.lookup.classref] paragraph 1 as follows:

  3. 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.

  4. Change _N4868_.6.5.6 [basic.lookup.classref] paragraph 4 as follows:

  5. 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]

  6. Change _N4868_.6.5.6 [basic.lookup.classref] paragraph 7 as follows:

  7. 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]

Date: 2021-02-24.00:00:00
N3092 comment US 23

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 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.

History
Date User Action Args
2014-03-03 00:00:00adminsetstatus: fdis -> c++11
2011-04-10 00:00:00adminsetmessages: + msg3295
2011-04-10 00:00:00adminsetstatus: ready -> fdis
2010-11-29 00:00:00adminsetmessages: + msg3046
2010-11-29 00:00:00adminsetstatus: drafting -> ready
2010-08-02 00:00:00admincreate