Введите псевдоним с тем же именем, что и тип - PullRequest
6 голосов
/ 23 апреля 2020

Действительно ли это C ++?

#include <iostream>


class Test {

    struct Inner {
    };

public:
    using Inner = Inner;  // Alias with same name as type
};

int main(int argc, const char * argv[]) {
    static_assert(std::is_pod<Test::Inner>::value, "");

    return 0;
}

Компилировать нормально с помощью clang, но не с G CC / Visual C ++ (сообщение об ошибке "Inner is private ...")

Ответы [ 2 ]

2 голосов
/ 23 апреля 2020

G CC и Visual C ++ верны.

Действительно, вы можете использовать using, чтобы фактически изменить доступ члена, например,

using Inner_ = Inner;

с помощью

static_assert(std::is_pod<Test::Inner_>::value, "");

в функции.

Но в случае, когда псевдоним типа имеет то же имя, что и член, C ++ требует, чтобы оператор разрешения области поиска выполнял поиск члена. Таким образом, в вашем случае Test::Inner относится к фактическому члену, а не к using, и поэтому компиляция должна завершиться неудачей, так как это private.


См. https://en.cppreference.com/w/cpp/language/qualified_lookup, и, в частности,

Квалифицированный поиск в области пространства имен N сначала рассматривает все объявления, расположенные в N, и все объявления, которые находятся во встроенных членах пространства имен N (и, транзитивно, в их встроенные члены пространства имен). Если в этом наборе нет объявлений, он рассматривает объявления во всех пространствах имен, названных директивами using, найденными в N, и во всех переходных элементах пространства имен N

.
0 голосов
/ 01 мая 2020

Я думаю, что в настоящее время Стандарт не может ответить, кто прав. P1787R4: Объявления и где их найти , кажется, благоприятствуют поведению Кланга:

[basi c .lookup]

Добавить параграфы:

В определенных контекстах включены только определенные виды объявлений. После любого такого ограничения любые объявления классов или перечислений отбрасываются, если найдены какие-либо другие объявления . [Примечание: тип (но не typedef-имя или шаблон) поэтому скрыт любой другой сущностью в своей области видимости. - примечание конца] Однако, если поиск только по типу, рассматриваются только объявления типов и шаблонов, специализация которых является типами; более того, если найдены декларатор typedef и декларация типа, к которому он относится, декларатор typedef отбрасывается вместо декларации типа.

PS Тип только поиск во второй части абзаца - это, примерно, поиск в подробный спецификатор типа , и это (typedef объявление отбрасывать) также согласуется с поведением Clang, где вы будете иметь ошибку доступа при использовании подробный спецификатор типа : std::is_pod<struct Test::Inner>.

Мотивация поведения Кланга выглядит как симметрия + согласованность.
Под симметрией я имею в виду, что если поиск в разработан спецификатор типа позволяет обратиться к скрытому объявлению класса / перечисления, тогда в не- уточненном спецификаторе типа , объявления класса / перечисления скрыты, если какое-либо объявление с тем же именем существует.
Под последовательностью я подразумеваю, что это правило применяется ко всем областям применения, включая класс.

...