GCC 3.4 новые правила разрешения имен
От: McSeem2 США http://www.antigrain.com
Дата: 17.06.04 03:44
Оценка: 6 (1)
Делаем так:
template<class T> base_class
{
public:
   int base_var;
};

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

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

Первый вопрос — почему так?
Второй вопрос — если так, то почему резолвится this->base_var? Ведь this это не base_class<T>, это — тот же самый derived_class<T>?
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re: GCC 3.4 новые правила разрешения имен
От: Шахтер Интернет  
Дата: 17.06.04 04:42
Оценка: 12 (1)
Здравствуйте, 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>Первый вопрос — почему так?


По стандарту. И не только gcc, но и VC++ 7.1 делает то же самое с опцией /Za.
Этот вопрос, по-моему, уже обсуждался в форуме. Можно глянуть Вандервуда и Джоссатиса C++ templates -- там это точно было.

Если коротко -- проблема в том, когда именно производить разрешение имен. В точке определения или в точке "воплощения" шаблона. В точке определения компилятор не может знать ничего о шаблонном базовом классе -- из-за специализации. Имя base_var не является dependent name в данном случае, поэтому разрешается(с ошибкой) в точке определения шаблона.

this -> base_var
base_class<T>::base_var -- dependent name (грубо говоря, имеет "существенную" зависимость от параметров шаблона).

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


this -> derived_class<T>::base_var -- вот так может быть более ясно

Можно ещё using использовать.
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re: GCC 3.4 новые правила разрешения имен
От: MaximE Великобритания  
Дата: 17.06.04 04:50
Оценка:
McSeem2 wrote:

> Делаем так:

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

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

Ради фана добавь перед определением derived_class<> глобальный int base_var; *

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


base_var — это argument dependant name. Так как компилятору об этом неизвестно (ты явно scope не указал через this-> или base_class<T>:), то он предполагает, что это обычное имя и осуществляет привязку в точке определения шаблона и просматривает derived_class<> scope, затем namespace scope, затем global scope.

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


Потому что ты явно указываешь компиятору scope этого имени и указываешь что нужно искать в scope этого класса и базовых классов, что откладывает поиск имени до момента инстанцирования.

* Именно поэтому в шаблонных классах удобно все члены (и дата, и ф-ции) префиксить this-> — это спасает от неожиданностей.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 beta
Re[2]: GCC 3.4 новые правила разрешения имен
От: Павел Кузнецов  
Дата: 17.06.04 15:06
Оценка:
> По стандарту. И не только gcc, но и VC++ 7.1 делает то же самое с опцией /Za.

VC++ 7.1 не поддерживает two phase name lookup, и, насколько мне известно, следующая версия тоже не будет.
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
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,
Андрей Тарасевич
http://files.rsdn.org/2174/val.gif
Re[3]: GCC 3.4 новые правила разрешения имен
От: Шахтер Интернет  
Дата: 18.06.04 00:05
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

>> По стандарту. И не только gcc, но и VC++ 7.1 делает то же самое с опцией /Za.


ПК>VC++ 7.1 не поддерживает two phase name lookup, и, насколько мне известно, следующая версия тоже не будет.


Тем не менее.

/* main.cpp */ 

#include <iostream>
#include <strstream>

using namespace std;

template <class T>
struct Base
 {
  int i;
  
  Base() : i(54321) {}
 };

int i=12345;

template <class T>
struct Test : Base<T>
 {
  void test()
   {
    cout << "i=" << i << endl ;
   }
 };

/* main() */ 

int main()
 {
  Test<int>().test();
 
  return 0;
 }


VC++ 7.1 /Za печатает 12345

Intel С++ 8.0 печатает 54321
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[4]: GCC 3.4 новые правила разрешения имен
От: Павел Кузнецов  
Дата: 18.06.04 02:13
Оценка:
> ПК>VC++ 7.1 не поддерживает two phase name lookup, и, насколько мне известно, следующая версия тоже не будет.
>
> Тем не менее. <...>

Да, это первые шаги в нужном направлении. К сожалению, насколько я знаю, реализацию полноценного two phase lookup и в следующей версии было решено не делать.
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: GCC 3.4 новые правила разрешения имен
От: McSeem2 США http://www.antigrain.com
Дата: 18.06.04 02:16
Оценка:
ПК>VC++ 7.1 не поддерживает two phase name lookup, и, насколько мне известно, следующая версия тоже не будет.

VC++ 7.1 вообще даже не парсит толком до момента инстанциирования.

template<class T> class A { public: void f() { int i } };


g++ ругается,
a.cpp: In method `void A<T>::f()':
a.cpp:1: parse error before `}'

Микрософты, что 6 что 7.1 — молчат как рыбы об лед.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[2]: GCC 3.4 новые правила разрешения имен
От: McSeem2 США http://www.antigrain.com
Дата: 18.06.04 02:31
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

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


АТ>'this->base_var' — зависимое выражение. Просто 'base_var' — независимое выражение. Отсюда и различия в разрешении имен, содержащихся в этих выражениях.


Спасибо!
Все-таки мне кажется более логичным писать типа:

template<class T> class derived_class
{
...
typedef base_class<T> base_type;
typedef derived_class<T> self_type;

  void f()
  {
     base_type::var;
  }
};


Хоть и больше писанины, но гораздо нагляднее.
А вот для виртуальных функций — только "this->"

Кстати, попутный вопрос — я до сих пор пишу template<class T>... Не собираются ли они в будущем упразнить такую форму декларации и заставить писать template<typename T>?
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[3]: GCC 3.4 новые правила разрешения имен
От: Павел Кузнецов  
Дата: 18.06.04 02:55
Оценка:
> Кстати, попутный вопрос — я до сих пор пишу template<class T>... Не собираются ли они в будущем упразнить такую форму декларации и заставить писать template<typename T>?

Вряд ли: без серьезных оснований никто не решится ломать огромное количество написанного кода — а в данном случае никаких оснований запрещать template<class T> не видно.
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.