crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Еще одна ошибка компилятора
LuckLess
  опции профиля:
сообщение 19.10.2007, 10:47
Сообщение #1


Студент
*

Группа: Новичок
Сообщений: 31
Регистрация: 10.10.2007
Пользователь №: 8

Спасибо сказали: 0 раз(а)




Репутация:   0  


нуу.. опять начну с кода...
template <class T>
class ATemplateBase
   {
public:
   void foo ()
      {
      static_cast<T*> (this)->i = 666;
      }
   };

class EatMe//:P
   {
   char m[4];
   };

class VS8ErrorClass : public EatMe, public ATemplateBase<VS8ErrorClass>
   {
public:
   VS8ErrorClass () : i (0)
      {

      }

   void foo ()
      {
      ATemplateBase::foo ();
      }

   int i;
   };


int main ()
   {
   struct FunnyStruct
      {
      VS8ErrorClass error;
      int devilsNumber;

      FunnyStruct () : devilsNumber (0)
         {

         }
      };
  
   FunnyStruct fs;
   std::cout << fs.error.i << " " <<  fs.devilsNumber << "\n";
   fs.error.foo ();
   std::cout << fs.error.i << " " <<  fs.devilsNumber << "\n";
   }


ну... вопервых почему этот код превельный..
static_cast<T*> должен сработать т.к.
Цитата
An rvalue of type “pointer to cv1 B,” where B is a class type, can be converted to an rvalue of type “pointer to cv2 D,”
where D is a class derived (clause 10) from B, if a valid standard conversion from “pointer to D” to “pointer to B” exists
(4.10), cv2 is the same cv-qualification as, or greater cv-qualification than, cv1, and B is not a virtual base class of D.


самое сложное тут ATemplateBase::foo ();
фактически такой вызов должен срботать т.к. есть такая штука как injected class name
Цитата
A class-name is inserted into the scope in which it is declared immediately after the class-name is seen. The class-name
is also inserted into the scope of the class itself; this is known as the injected-class-name. For purposes of access
checking, the injected-class-name is treated as if it were a public member name.

Цитата
In a derived class, the lookup of a base class name will find the injected-class-name instead of the name of the
base class in the scope in which it was declared.

Цитата
Like normal (non-template) classes, class templates have an injected-class-name (clause 9). The injected-class-name can
be used with or without a template-argument-list.When it is used without a template-argument-list, it is equivalent to
the injected-class-name followed by the template-parameters of the class template enclosed in <>.

так что ATemplateBase::foo (); нормальный вызов т.к. ATemplateBase это injected class name который
можно использовать без шаблонных параметров.

Вот.. собстно эффект от этого кода... в 8-й студии все очень плохо... переменная devilsNumber зачемто равно 666 ))).
Одна из гцц нескомпилировала это дело.. что тоже плохо.. но заметно лучше чем результат студии

как избавится от этого...? просто использовать injected-class-name с шаблонными параметрами.
ATemplateBase<VS8ErrorClass>::foo ();

техника такого статик каста прменяется во многих ATL-ых базовых классах.. и бывает краайне неудобно
вызывать их метод полностью выписывая шаблонные параметры, так как их там часто очень много :D

ждем второго сервис пака к студии?))
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Tonal
  опции профиля:
сообщение 6.12.2007, 10:02
Сообщение #2


Активный участник
***

Группа: Участник
Сообщений: 452
Регистрация: 6.12.2007
Из: Новосибирск
Пользователь №: 34

Спасибо сказали: 69 раз(а)




Репутация:   17  


Такое и не должно компилироваться, из за
...
  void foo ()
      {
      ATemplateBase::foo ();
      }
...

Здесь, по стандарту, должна быть явная классификация шаблона.
У VC это довольно старая бага.
Там таких полно: я когда их движёк регэкспов (гретту) попробывал использовать под gcc там подобные глюки пачками сыпались. А часто и более замысловатые.

Эта та проблема довольно просто решается:
...
class VS8ErrorClass : public EatMe, public ATemplateBase<VS8ErrorClass>
   {
typedef ATemplateBase<VS8ErrorClass> ATemplateBase;
public:
...


P.S. ошибка, которая вылезает в VC8 похоже связана не с этим а с выравниванием - где то он похоже путается.
Если EatMe убрать из предков, что получится? А если поменять его местами с ATemplateBase?

Сообщение отредактировал Tonal - 6.12.2007, 10:06
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
LuckLess
  опции профиля:
сообщение 7.12.2007, 11:32
Сообщение #3


Студент
*

Группа: Новичок
Сообщений: 31
Регистрация: 10.10.2007
Пользователь №: 8

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(Tonal @ 6.12.2007, 11:02) *
P.S. ошибка, которая вылезает в VC8 похоже связана не с этим а с выравниванием - где то он похоже путается.
Если EatMe убрать из предков, что получится? А если поменять его местами с ATemplateBase?

Студия просто прибавляет двойное смещение к this-у для базового класса зачемто. Смотрел в асме даже :p
Если базовый класс будет первыйм то двойное смещение будет 0 == 0*2 и все будет ок :D
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Tonal
  опции профиля:
сообщение 7.12.2007, 11:52
Сообщение #4


Активный участник
***

Группа: Участник
Сообщений: 452
Регистрация: 6.12.2007
Из: Новосибирск
Пользователь №: 34

Спасибо сказали: 69 раз(а)




Репутация:   17  


Зачем прибавляет - понятно - в ATemplateBase указатель this смещён относительно VS8ErrorClass.
Почему дважды - тоже понятно - первый раз - смещение ATemplateBase относительно обшего, второй смещение i относительн ATemplateBase в общем.

Формально всё правильно, ведь sizeof любого класса > 0 и равен текущему выравниванию.

Ошибается оно, похоже на "оптимизации базовых классов": стандартом разрешено не увеличивать размер в случае наследования от "пустого" класса. Пустым будет класс не содержащий данных членов, виртуальных функций и виртуального наследования не в себе не в своих предках.

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

Проверить это можно поиграв размерами и пустотой классов ATemplateBase и EatMe
Ну и обход понятен, если так- добавить фиктивный член в ATemplateBase.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 1.2.2023, 12:44