Why doesn't private inheritance resolve ambiguity for static functions ? (tested in MSVC)

812 Views Asked by At

I'm wondering why a call to a static function is ambiguous, even when one of the two is obviously impossible to call as it is private. I was hoping I could use private / protected inheritance to help the compiler solve the ambiguity.

Is it specific to MSVC or is it somehow specified in the standard ?

struct A
{
    static int num() { return 0; }
};

struct B
{
    static int num() { return 1; }
};

struct C : public A, private B
{};

int main()
{
     C::num(); // Ambiguous access of num
}

The background is that I was trying a way of reusing an overloading behavior (the one in A) in many derived classes (C,D,E,F,G) by inheriting it, to adhere somehow to a rule of Don't Repeat Yourself.

3

There are 3 best solutions below

3
On BEST ANSWER

Yes it is specified in the C++ Standard, section §3.4 [basic.lookup]

The access rules (Clause 11) are considered only once name lookup and function overload resolution (if applicable) have succeeded

Name lookup doesn't care about accessibility : it finds both A::num and B::num, so there is an ambiguity for the compiler.

You can explicitly call A::num with :

C::A::num();

If you explicitly try to call B::num, then your compiler will indeed emit an access error :

C::B::num(); // Error

You can also explicitly bring the base name into scope within the derived class, which will fix the ambiguity :

struct C : public A, private B
{
    using A::num;    
};
0
On

Private members are intentionally considered for overload resolution.

Suppose you have

class C {
public:
  static void f(int);
  static void g();
private:
  static void f(long);
};

void C::g() {
  f(0L); // okay
}
void g() {
  f(0L); // error, does not silently call f(int)
}

Making only public members available during overload resolution causes highly surprising re-interpretations of code, where code that looks like it should work the exact same way would silently call different overloads.

Making such code an error was considered less troublesome than the alternative.

0
On

To help compiler you can do this

 struct C : public A, private B
 {
      using A::num;
 };