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


1309. Incorrect note regarding lookup of a member of the current instantiation

Section: 13.8.3.2  [temp.dep.type]     Status: CD4     Submitter: Johannes Schaub     Date: 2011-05-05

[Moved to DR at the May, 2015 meeting.]

The note in 13.8.3.2 [temp.dep.type] paragraph 7 reads,

[Note: the result of name lookup differs only when the member of the current instantiation was found in a non-dependent base class of the current instantiation and a member with the same name is also introduced by the substitution for a dependent base class of the current instantiation. —end note]

However, this is not correct. Consider the following example:

  struct Y { int X; };

  template<typename T>
  struct A : Y {
   enum B : int;
   void f() { A::X; } // finds Y::X here!
  };

  template<typename T>
  enum A<T>::B : int {
   X // introduces member A::X into A<T>!
  };

  void g() { A<int> a; a.f(); }

A::X is a member of the current instantiation, so paragraph 7 requires it to be looked up again when instantiating and to give a diagnostic if the lookup differs from the lookup in the definition context. The note incorrectly indicates that this can only happen if the conflicting name was introduced by a dependent base class.

Proposed resolution (August, 2011) [SUPERSEDED]:

Change 13.8.3.2 [temp.dep.type] paragraph 7 as follows:

...If the result of this lookup differs from the result of name lookup in the template definition context, name lookup is ambiguous. [Note: the result of name lookup differs only when the member of the current instantiation was found in a non-dependent base class of the current instantiation and a member with the same name is also introduced by the substitution for a dependent base class of the current instantiation. —end note] [Example:

  struct A {
    int m;
  };

  struct B {
    int m;
  };

  template<typename T>
  struct C : A, T {
    int f() { return this->m; } // finds A::m in the template definition context
  };

  int g(C<B> cb) {
    return cb.f();              // error: finds both A::m and B::m in the template instantiation context
  }

end example]

Notes from the December, 2011 teleconference:

Changes to the exposition were suggested and the issue returned to "drafting" status.

Proposed resolution (November, 2014):

Change 13.8.3.2 [temp.dep.type] paragraph 7 as follows:

...If the result of this lookup differs from the result of name lookup in the template definition context, name lookup is ambiguous. [Note: the result of name lookup differs only when the member of the current instantiation was found in a non-dependent base class of the current instantiation and a member with the same name is also introduced by the substitution for a dependent base class of the current instantiation. —end note] [Example:

  struct A {
    int m;
  };

  struct B {
    int m;
  };

  template<typename T>
  struct C : A, T {
    int f() { return this->m; }  // finds A::m in the template definition context
  };

  template int C<B>::f();        // error: finds both A::m and B::m

end example]