26

см следующего кодаСтранное поведение с помощью декларирования

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

Всех НКУ 6.1, лязг 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 сделать все компиляторы работают нормально), но я хочу знать, если эта странная ошибка, что говорит стандарт.

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

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

Я предполагаю, что это связано с тем, как работает поиск имени для 'A' внутри' C'.Сначала он проверяет, не объявлено ли что-либо с именем 'A' в области' C' перед 'использованием'. Поскольку он не находит его, он проверяет его в области 'B', так как это базовый класс. И в случае, если он не найдет 'A' в области' B ', он будет выглядеть в« глобальном пространстве имен ». Но каким-то образом «частное наследование» 'A' by' B' останавливается при втором поиске i.e внутри области 'B'. Поскольку он работает с использованием имени «полностью квалифицированного», это заставляет меня думать, что реальная проблема должна быть в тех же строках. – Arunmu

+4

http://eel.is/c++draft/class.access.spec#5 кажется актуальным –

+0

@PiotrSkotnicki Спасибо, он напрямую отвечает на вопрос. Но, можете ли вы дать мне разумное значение для этого правила? –

ответ

28

Согласно правилу unqualified name lookup:

(курсив мой)

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

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

И ::A определяет имя в глобальном масштабе и решает проблему, которая делает ее qualified name lookup.

2

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

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

Смежные вопросы