Здравствуйте, 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' — независимое выражение. Отсюда и различия в разрешении имен, содержащихся в этих выражениях.