Поиск имени базового класса после наследования конструктора
Рассмотрим следующий код:
struct base {};
struct derived : public base {
using base::base;
base foo() const; // how does name lookup on 'base' here work?
};
Интуитивно понятно, что этот код действителен, и он компилируется (проверено с помощью gcc и clang).
Тем не менее, я хотел бы понять, что в стандарте делает его действительным. В частности, я хотел бы понять, как поиск имени для base
в base foo()
находит тип базового класса, а не унаследованный конструктор.
Вот мой анализ стандартной формулировки, показывающий, что она должна разрешаться для конструктора. Это, вероятно, неправильно, но я хотел бы понять, где я иду не так.
Я начал с [class.member.lookup] p1
:
Поиск имени члена определяет значение имени (id-выражения) в области видимости класса. [...] Для id-выражения поиск имени начинается в области видимости класса
this
p7
говорит нам, каков результат поиска имени:
Результат поиска имени для [имя члена]
f
в [области видимости]C
является набором объявлений S(f, C)
Я пытаюсь следовать этой процедуре с C
являющийся derived
, а также f
быть использование base
в base foo()
,
"Набор деклараций" определяется в p3
:
Набор для поиска
f
вC
называется S(f, C), состоит из двух наборов компонентов: набор объявлений, набор членов с именемf
; [...]
p4
говорит нам, что входит в набор объявлений:
Если
C
содержит декларацию имениf
набор объявлений содержит каждое объявлениеf
объявлено вC
это удовлетворяет требованиям языковой конструкции, в которой происходит поиск.
using base::base
это объявление имени base
(f
) в derived
(C
). В этом параграфе приводятся примеры того, что означает, что объявление не удовлетворяет требованиям языковой конструкции, в которой происходит поиск, но там нет ничего, что могло бы исключить using base::base
из этого поиска.
Далее дальше вниз по p3
нам рассказывают, как обрабатываются using-объявления в наборе объявлений:
В наборе объявлений использование-объявлений заменяется набором назначенных членов, которые не скрыты или не переопределены членами производного класса.
Так что участники делают using base::base
назначить? Мне кажется, что ответили [class.qual] p2
:
При поиске, в котором имена функций не игнорируются, а спецификатор вложенного имени назначает класс
C
:
если имя указано после спецификатора вложенного имени, при поиске в
C
, является введенным именем классаC
, или жев объявлении использования, которое является объявлением члена, если имя, указанное после спецификатора вложенного имени, совпадает с идентификатором [...] в последнем компоненте спецификатора вложенного имени
вместо этого имя считается именем конструктора класса
C
,
Существует сноска, поясняющая, что означает "поиск, в котором имена функций не игнорируются":
Поиск, в котором имена функций игнорируются, включает имена, появляющиеся в спецификаторе вложенного имени, подробном спецификаторе типа или базовом спецификаторе.
Ни один из этих случаев не подходит для поиска имени, о котором идет речь, поэтому мне кажется, что этот параграф применим и говорит, что using base::base
обозначает конструктор (что также является интуитивно понятным, учитывая, что это объявление наследующего конструктора).
Найдя объявление (обозначающее конструктор базового класса) в области видимости производного класса, мы продолжаем [class.member.lookup] p4
:
Если результирующий набор объявлений не пустой, набор подобъектов содержит
C
Сам, и расчет завершен.
Таким образом, поскольку поиск имени нашел результат в области производного класса, он не переходит к поиску в области базового класса (где он найдет имя введенного класса). base
). [В качестве отступления, даже если поиск по имени продолжался в области видимости базового класса, я не вижу ничего, что могло бы устранить неоднозначность между конструктором и именем введенного класса ].
Где мои рассуждения идут не так?
1 ответ
Стандарт делает все возможное, чтобы указать, что конструктор не имеет имени. Его нельзя найти по имени, потому что у него нет имени.
C++ 11 §12.1 / 1C + 11 §12.1 / 2"У конструкторов нет имен.
" Поскольку конструкторы не имеют имен, они никогда не обнаруживаются при поиске имен.