пожалуйста, смотрите следующий код
struct A { using type = int; };
struct B : private A {};
struct C : B { using base_type = A; };
Все gcc 6.1, clang 3.8 и msvc 2015 update 3 отказываются компилировать это, так как A
не доступно имя внутри C
поскольку A
является частной базой B
, Кажется, что GCC думает A
в using base_type = A
ссылается на конструктор по умолчанию A
, MSVC и лязг, кажется, нет.
Возможно, ошибка компиляции связана с внедрением имен, вызванных наследованием (потому что изменение using base_type = A
в using base_type = ::A
заставить все компиляторы работать нормально), но я хочу знать, является ли эта странная ошибка стандартом.
Конкретнее,
A::type
, A
это просто имя класса (хотя gcc неверно интерпретирует его как имя функции), которое вводится в C
не внутри A
ни B
, Почему это имя считается частным B
?Согласно правилу поиск безусловного имени:
(акцент мой)
Для неквалифицированного имени, то есть имени, которое не отображается справа от оператора разрешения контекста :: поиск имени проверяет области, как описано ниже, пока не найдет хотя бы одно объявление любого вида, в это время поиск останавливается и дальнейшие области не рассматриваются.
Итак, имя A
будет сначала найден в области видимости базового класса, имя в глобальном пространстве имен здесь не будет рассматриваться. После этого выполняется проверка прав доступа, а затем компиляция не удалась.
А также ::A
указывает имя в глобальной области видимости и решает проблему, что делает его поиск подходящего имени.
Публикация моего комментария как ответа (больше похоже на ответ, чем на комментарий):
Я предполагаю, что это связано с тем, как поиск имени для A
внутри C
работает. Сначала он проверяет, объявлено ли что-либо с именем A
в объеме C
Перед использованием. Поскольку он не находит, он проверяет его в объеме B
так как это базовый класс. А также в случае он не находит A в области видимости Bs, это будет выглядеть в global namespace
, Но каким-то образом частное наследство A
от B
останавливается при втором поиске, т. е. в рамках B
, Поскольку он работает с использованием fully qualified
имя, которое заставляет меня думать, что реальная проблема должна быть в том же духе