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

Странное поведение использования-объявления

см. следующий код

struct A { using type = int; };
struct B : private A {};
struct C : B { using base_type = A; };

Все обновления gcc 6.1, clang 3.8 и msvc 2015 3 отказываются компилировать это, так как A не является доступным именем внутри C, поскольку A является частной базой B. Кажется, что gcc думает, что A в using base_type = A относится к конструктору по умолчанию A. msvc и clang выглядят не так.

Возможно, ошибка компиляции связана с введением имен, вызванных наследованиями (поскольку изменение using base_type = A в using base_type = ::A делает все компиляторы работоспособными), но я хочу знать, является ли эта странная ошибка тем, что говорит стандарт.

Более конкретно,

  • Как я понял, не нравится A::type, A - это просто имя класса (хотя gcc неправильно интерпретирует его как имя функции), которое вводится в C не внутри A, ни B. Почему это имя считается закрытым для B?
  • Если эта ошибка компиляции считается ошибкой или является краевым случаем спецификаций стандарта?
4b9b3361

Ответ 1

В соответствии с правилом неквалифицированный поиск имени:

(акцент мой)

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

Итак, имя A будет найдено сначала в области базового класса, имя в глобальном пространстве имен здесь не рассматривается. После этого выполняется проверка прав доступа, а затем сбой компиляции.

И ::A указывает имя в глобальной области действия и решает проблему, что делает ее квалифицированным именем поиска.

Ответ 2

Проводя свой комментарий в качестве ответа (похоже, ответ больше, чем комментарий):

Я предполагаю, что это связано с тем, как работает поиск имени A внутри C. Сначала он проверяет, не объявлено ли что-либо с именем A в области C перед использованием. Поскольку он не находит его, он проверяет его в области B, так как он является базовым классом. И в случае, если он не находит A в области Bs, он будет выглядеть в global namespace. Но почему-то частное наследование A на B прекращается при втором поиске i.e внутри области B. Поскольку он работает с использованием имени fully qualified, это заставляет меня думать, что реальная проблема должна быть в тех же строках.