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
Consider:
template<int I> struct C { }; struct B { C<1> foo(); C<1> bar(); }; struct D : B { using B::foo; C<2> foo(this B &); using B::bar; C<2> bar(this D &); }; struct DD : D { using D::foo; using D::bar; }; void bar(D d, DD dd) { d.foo(); dd.foo(); d.bar(); dd.bar(); }
Which functions are called?
Subclause 9.9 [namespace.udecl] paragraph 11 specifies:
The set of declarations named by a using-declarator that inhabits a class C does not include member functions and member function templates of a base class that correspond to (and thus would conflict with) a declaration of a function or function template in C.
The definition of "corresponds" considers the type of the implicit object parameter, which is a deviation from the status quo ante for a simple example like this one:
struct B {
void f(); // #1
};
struct D : B {
void f();
using B::f; // should not name #1
};
Suggested resolution:
Change in 9.9 [namespace.udecl] paragraph 11 as follows:
The set of declarations named by a using-declarator that inhabits a class C does not include member functions and member function templates of a base class that, when considered as members of C, correspond to (and thus would conflict with) a declaration of a function or function template in C.[ Example:
struct B { virtual void f(int); virtual void f(char); void g(int); void h(int); void i(); void j(); }; struct D : B { using B::f; void f(int); // OK, D::f(int) overrides B::f(int) using B::g; void g(char); // OK using B::h; void h(int); // OK, D::h(int) hides B::h(int) using B::i; void i(this B &); // OK using B::j; void j(this D &); // OK, D::j() hides B::j() }; void k(D* p) { p->f(1); // calls D::f(int) p->f('a'); // calls B::f(char) p->g(1); // calls B::g(int) p->g('a'); // calls D::g(char) p->i(); // calls B::i, because B::i as a member of D is a better match than D::i p->j(); // calls D::j } ...