Подтвердить что ты не робот

Вызов метода и типа метода С++ неоднозначность

Я надеюсь, что название фактически описывает то, что я хотел спросить...

Я написал фрагмент кода, который компилируется с помощью gcc и работает так, как я предполагал. Однако он не компилируется с llvm, и код выполняется по-разному при компиляции с icc!
Вот пример проблемы:

#include <iostream>

using std::cout; using std::endl;

class A {
public:
  virtual void foo() { cout << "A::foo()" << endl; }
};

class B : public A {
public:
  typedef A  base;
  virtual void foo() { cout << "B::foo()" << endl; }
};

int main() {
  typedef B  base;
  base* bp = new B();
  bp->base::foo(); 
}

Выход gcc: A:: foo()
icc output: B:: foo()

Может кто-нибудь объяснить, что говорит стандарт об этом случае?

4b9b3361

Ответ 1

Из С++ 11, §3.4.5/4:

Если id-выражение в доступе к члену класса является квалифицированным идентификатором форма
    class-name-or-namespace-name::...
имя класса или имени пространства имен после. или → оператор сначала просматривается в классе выражение объекта и имя, если найдено, используется. В противном случае это искал в контексте всего постфиксного выражения.

Я не думаю, что это может быть яснее. Это находит B::base, поэтому вывод должен быть A::foo().

Ответ 2

Я думаю, что эта часть стандарта имеет значение:

3.4.3.1 Члены класса [class.qual]

1) Если спецификатор вложенного имени квалифицированного идентификатора назначает класс, имя, указанное после Вложенные имена в именах классов (10.2), за исключением случаев, перечисленных ниже. Название должно представлять одно или больше членов этого класса или одного из его базовых классов (п. 10). [Примечание. Член класса может ссылаться на использование идентификатора с квалификацией указывают на его потенциальный охват (3.3.7). -end note] Исключения из правилом поиска имени является следующее:

- имя деструктора посмотрел вверх, как указано в 3.4.3;

- идентификатор типа конверсии Идентификатор функции преобразования просматривается таким же образом, как и идентификатор типа преобразования в доступе к члену класса (см. 3.4.5);

- имена в шаблоне-аргументе идентификатора шаблона просматриваются в контексте в котором происходит все постфиксное выражение.

- поиск имени указанная в использовании-декларации (7.3.3), также находит класс или имена перечислений, скрытые в той же области (3.3.10).

base:: в этом случае, как представляется, "назначает" класс, поэтому поиск выполняется в рамках класса. Я не вижу, как может применяться любой из случаев исключения, поэтому он является областью действия класса, так как base эквивалентен A.

(5.1.1-8 указывает, что в этом случае он является квалифицированным идентификатором и применяется 3.4.3.1)