Почему частное наследование не разрешает неоднозначность для статических функций? (проверено в MSVC)

Мне интересно, почему вызов статической функции неоднозначен, даже если одно из двух явным образом невозможно вызвать, поскольку оно является частным. Я надеялся, что смогу использовать частное / защищенное наследование, чтобы помочь компилятору решить эту неоднозначность.

Это специфично для MSVC или как-то указано в стандарте?

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
}

Предпосылкой является то, что я пытался использовать способ перегрузки (тот, что в A) во многих производных классах (C,D,E,F,G), наследуя его, чтобы каким-то образом придерживаться правила "Не повторять". Сам.

3 ответа

Решение

Да, это указано в стандарте C++, раздел §3.4 [basic.lookup]

Правила доступа (пункт 11) рассматриваются только после успешного поиска имени и разрешения перегрузки функции (если применимо)

Поиск имени не заботит о доступности: он находит оба A::num а также B::num, так что есть неопределенность для компилятора.

Вы можете явно позвонить A::num с:

C::A::num();

Если вы явно пытаетесь позвонить B::numтогда ваш компилятор действительно выдаст ошибку доступа:

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

Вы также можете явно ввести базовое имя в область видимости в производном классе, что устранит неоднозначность:

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

Чтобы помочь компилятору, вы можете сделать это

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

Частные участники намеренно рассматриваются для разрешения перегрузки.

Предположим, у вас есть

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)
}

Если во время разрешения перегрузки доступны только открытые члены, это вызывает удивительную реинтерпретацию кода, когда код, который выглядит так, как будто он должен работать точно так же, молча вызывал бы разные перегрузки.

Создание такого кода ошибки считалось менее хлопотным, чем альтернатива.

Другие вопросы по тегам