Почему общедоступные типы членов базового класса шаблона скрыты по умолчанию?

template<typename T>
struct A
{
    using U = T;
};

template<typename T>
struct B : A<T>
{
    B(typename A<T>::U) {} // okay
    B(U) {} // error: unknown type name 'U'
};

int main()
{
    return typename B<int>::U{}; // okay
}

Почему открытые типы членов базового класса шаблона скрыты по умолчанию?


person xmllmx    schedule 24.04.2021    source источник
comment
Поиск зависимого имени.   -  person Peter    schedule 24.04.2021
comment
выглядит как дубликат stackoverflow.com/questions/610245/   -  person user7860670    schedule 24.04.2021


Ответы (1)


Поисковый термин для дальнейшего исследования — двухэтапный поиск имени.

Короче говоря, компилятор пытается разрешить как можно больше имен, используемых шаблоном, в точке определения шаблона. Некоторые имена — так называемые зависимые имена — не могут быть разрешены на данном этапе и должны быть отложены до фактического создания экземпляра шаблона и определения его параметров. Грубо говоря, это имена, которые появляются из синтаксиса и зависят от параметров шаблона.

U само по себе не является зависимым именем, поэтому компилятор пытается разрешить его при компиляции определения B. В настоящее время он не может заглянуть внутрь A<T> — он не знает, каким будет T, и будет ли специализация A для этого T, которая может объявить или не объявить члена с именем U. Затем поиск не находит объявления для U, отсюда и ошибка.

U в A<T>::U является зависимым именем, его поиск откладывается до тех пор, пока не будет создан экземпляр B<int>. В этот момент компилятор также создает экземпляр A<int> и может искать внутри него объявление U.

Вот почему вам нужно писать typename в typename A<T>::U. Компилятор не может искать объявление зависимого имени U, но он должен знать, по крайней мере, должно ли оно быть типом или нетипом, так как от этого зависит низкоуровневый лексический анализ (классический пример: X*Y; может быть проанализировано как объявление указателя или выражение с использованием умножения, в зависимости от того, является ли X типом). Таким образом, правило состоит в том, что зависимое имя считается относящимся к нетипу, если ему не предшествует ключевое слово typename.

person Igor Tandetnik    schedule 24.04.2021