Поиск имени базового класса после наследования конструктора

Рассмотрим следующий код:

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-expression) в области действия класса. [...] Для 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-declarations заменяется набором назначенных членов, которые не скрыты и не переопределены членами производного класса.

Итак, каких членов обозначает using base::base? Мне кажется, что на это ответил [class.qual] p2:

В поиске, в котором имена функций не игнорируются, а описатель вложенного имени назначает класс C:

  • если имя, указанное после описателя вложенного имени, при поиске в C является введенным именем класса C или

  • в объявлении-использования, которое является объявлением-членом, если имя, указанное после описателя вложенного-имени, совпадает с идентификатор [...] в последнем компоненте описателя вложенного имени

вместо этого имя считается именем конструктора класса C.

Существует сноска, разъясняющая, что означает «поиск, в котором имена функций не игнорируются»:

Поиски, в которых игнорируются имена функций, включают имена, появляющиеся в вложенном-спецификатор-имени, спецификатор-уточненного-типа или базовый-спецификатор.

Ни один из них не относится к рассматриваемому поиску имени, поэтому мне кажется, что этот абзац применим и говорит, что using base::base обозначает конструктор (что также интуитивно понятно, учитывая, что это объявление наследующего конструктора).

Найдя объявление (обозначающее конструктор базового класса) в области действия производного класса, мы продолжаем следовать [class.member.lookup] p4:

Если результирующий набор объявлений не пуст, набор подобъектов содержит сам C, и расчет завершен.

То есть, поскольку поиск имени нашел результат в области действия производного класса, он не переходит к поиску в области действия базового класса (где было бы найдено внедренное имя класса base). [Кроме того, даже если поиск имени продолжится в области действия базового класса, я не вижу ничего, что устраняло бы неоднозначность между конструктором и внедренным именем класса].

Где мои рассуждения идут не так?


person HighCommander4    schedule 08.01.2016    source источник


Ответы (1)


Стандарт делает все возможное, чтобы указать, что конструктор не имеет имени. Его нельзя найти по имени, потому что у него нет имени.

C++11 §12.1/1

Конструкторы не имеют имен.

C+11 §12.1/2

Поскольку у конструкторов нет имен, они никогда не обнаруживаются при поиске по имени.

person Cheers and hth. - Alf    schedule 08.01.2016
comment
Тогда что это за бит в [class.qual] p2, который говорит, что имя вместо этого считается именем конструктора? - person HighCommander4; 08.01.2016
comment
@HighCommander4: предположительно, речь идет об использовании приведения функциональной нотации для вызова конструктора. - person Cheers and hth. - Alf; 08.01.2016
comment
Но что исключает применение этого абзаца к using base::base? - person HighCommander4; 08.01.2016
comment
извините, теперь я просмотрел абзац, и он продолжает: такое имя конструктора должно использоваться только в идентификаторе декларатора объявления, которое называет конструктор, или в объявлении использования. В этом абзаце также есть примечание: Примечание. Например, конструктор не является приемлемым результатом поиска в уточненном спецификаторе типа, поэтому конструктор не будет использоваться вместо введенного имени класса. — конец примечания. Где вы читаете это, что не включает этот текст? - person Cheers and hth. - Alf; 08.01.2016
comment
Итак, using base::base — это декларация использования. - person HighCommander4; 08.01.2016
comment
да. И это относится к конструктору. - person Cheers and hth. - Alf; 08.01.2016
comment
Тогда почему конструктор не становится результатом поиска имени члена, когда объявления using заменяются набором назначенных членов, которые не скрыты и не переопределены членами производного класса? - person HighCommander4; 08.01.2016
comment
Можете указать источник этой цитаты? Не уверен, что смогу ответить на него в любом случае, но это обязательно поможет другим. - person Cheers and hth. - Alf; 08.01.2016
comment
Я процитировал его в своем посте. Это от [class.member.lookup] p3. - person HighCommander4; 08.01.2016
comment
Что ж, контекст поиска типа результата функции base - это обычный поиск имени. А затем срабатывает так и не найденный во время поиска имени. Это намного старше (с 1998 г.), чем наследование конструктора (с 2011 г.). Возможно, наследование конструктора не было точно определено. Но старые правила, правила, так сказать. :) - person Cheers and hth. - Alf; 08.01.2016
comment
Хорошо спасибо. Я думаю, мне просто не было ясно, что один из этих абзацев имеет приоритет над другим. - person HighCommander4; 08.01.2016