Re: GCC 3.4 новые правила разрешения имен
От: Андрей Тарасевич Беларусь  
Дата: 17.06.04 18:13
Оценка: 170 (12)
Здравствуйте, McSeem2, Вы писали:

MS>Делаем так:

MS>
MS>template<class T> base_class
MS>{
MS>public:
MS>   int base_var;
MS>};

MS>template<class T> derived_class : public base_class<T>
MS>{
MS>public:
MS>   int f()
MS>   {
MS>      return base_var;
MS>   }
MS>};
MS>

MS>И он не видит base_var. Видит только this->base_var
MS>или (что лучше) base_class<T>::base_var.

MS>Первый вопрос — почему так?


Во-первых, стоит упомянтуть, что просто 'base_var' — это так называемое неквалифицированное имя, 'base_class<T>::base_var' — это квалифицированное имя, а 'this->base_var' — это доступ к члену класса. Разрешение имен в этих трех случаях управляется тремя различными разделами стандарта языка — '3.4.1 Unquialified name lookup', '3.4.3 Qualified name lookup' и '3.4.5 Class member access' соответственно. Неудивительно, что правила разрешения имен в каждом случае отличаются.

Во-вторых, даже более важно в данном случае то, в процессе разрешения имен существует ряд специфичных для шаблонов особенностей, описанные внутри разделов 14.6.xxx. Одним из ключевых моментов при этом является то, классифицируется ли контекст (в данном случае — выражение), в котором использовано данное имя, зависимым (dependent) или независимым (non-dependent) от параметров шаблона. Разрешение имен в зависимых контекстах откладывается до момента инстанциирования, когда конкретные аргументы шаблона уже известны. Разрешение имен в независимых контекстах делается сразу.

В твоем примере выражение 'this->base_var' является зависимым, потому что его подвыражение 'this' является зависимым (см. 14.6.2.2/1). Подвыражение 'this', в свою очередь, является зависимым, потому что тип 'derived_class' является зависимым (см. 14.6.2.2/2). Тип 'derived_class' является зависимым, потому что он включает зависимый тип 'base_class<T>' (см. 14.6.2.1/1 и 3.9.2/1). Поэтому разрешение имени 'base_var' откладывается до момента инстанциирования.

Выражение 'base_class<T>::base_var' является зависимым по аналогичным причинам.

А вот выражение 'base_var' зависимым не является (оно просто не подходит ни под один пункт определения зависисмого выражения) поэтому имя 'base_var' в данном случае будет разрешаться сразу, по правилам 3.4.1, но с учетом поправки 14.6.2/3, где сказано, что зависящий от параметра шаблона базовый класс не рассматривается в процессе разрешения имен. Т.е. в твоем примере при разрешении простого 'base_var' из описанного в 3.4.1 процесса исключается рассмотрение базового класса. Понятно, что при этом имя найдено не будет.

MS>Второй вопрос — если так, то почему резолвится this->base_var? Ведь this это не base_class<T>, это — тот же самый derived_class<T>?


'this->base_var' — зависимое выражение. Просто 'base_var' — независимое выражение. Отсюда и различия в разрешении имен, содержащихся в этих выражениях.
Best regards,
Андрей Тарасевич
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.