Страниц: [1]
  Печать  
Автор Тема: Грабли с темплейтами  (Прочитано 3424 раз)
LP006688
Jr. Member
**
Offline Offline

Сообщений: 76



Просмотр профиля
« : Июня 26, 2009, 02:33:31 pm »

Код:
template<class TYPE> class List;
template<class TYPE> class PtrList;

template<class TYPE>
class LNode
{
friend class List<TYPE>;
friend class PtrList<TYPE>;
bool lock;
LNode<TYPE> *prev,*next;
TYPE body;

LNode(const TYPE &ref);
~LNode(void);
};

template<class TYPE>
class List
{
protected:
bool ok;
int (*match)(const TYPE *,const TYPE *);
unsigned size;
pthread_mutex_t CS;
LNode<TYPE> *start,*stop;

public:
List(void);
virtual ~List(void);
LNode<TYPE> *AddHead(const TYPE &ref);
void AddHead(const List &list);
LNode<TYPE> *AddTail(const TYPE &ref);
void AddTail(const List &list);
int Clear(void);
int Count(const TYPE &find);
virtual bool DelHead(void);
virtual bool DelTail(void);
int Del(const TYPE &ref);
virtual bool DelNext(LNode<TYPE> *&ptr);
virtual bool DelPrev(LNode<TYPE> *&ptr);
LNode<TYPE> *Find(const TYPE &find);
LNode<TYPE> *Find(const TYPE &find,LNode<TYPE> *&ptr);
void Free(const TYPE &ref);
void Free(LNode<TYPE> *ptr);
LNode<TYPE> *Free(void);
LNode<TYPE> *GetHead(void) const { return(start); }
LNode<TYPE> *GetTail(void) const { return(stop); }
TYPE Head(void) const { return(start->body); }
void Lock(const TYPE &ref);
void Lock(LNode<TYPE> *ptr);
bool Locked(const TYPE &ref);
bool Locked(LNode<TYPE> *ptr);
TYPE &Next(LNode<TYPE> *&ptr) const;
bool OK(void) const { return(ok); }
TYPE &Prev(LNode<TYPE> *&ptr) const;
void SetMatch(int (*cmp)(const TYPE *,const TYPE *)) { match=cmp; }
int Size(void) const { return(size); }
void Sort(void *ctx,int (*cmp)(void *,const TYPE *,const TYPE *));
TYPE Tail(void) const { return(stop->body); }
LNode<TYPE> *operator[](unsigned index);
TYPE &operator[](LNode<TYPE> *ptr) { return(ptr->body); }
List<TYPE> &operator=(const List &list);
protected:
static int Match(const TYPE *one,const TYPE *two) { return(memcmp(one,two,sizeof(TYPE))); }
};

template<class TYPE>
class PtrList:public List<TYPE>
{
public:
~PtrList(void);
bool DelHead(void);
bool DelTail(void);
bool DelNext(LNode<TYPE> *&ptr);
bool DelPrev(LNode<TYPE> *&ptr);
};

Далее идет глюк. Тут все в порядке:

Код:
template<class TYPE>
List<TYPE>::~List(void)
{
LNode<TYPE> *ptr,*nxt;

if(size&&pthread_mutex_lock(&CS)==EOK)
{
for(ptr=start;ptr;ptr=nxt)
{
nxt=ptr->next;
delete ptr;
}
size=0;
start=stop=NULL;
pthread_mutex_unlock(&CS);
}
pthread_mutex_destroy(&CS);
}

А тут идут ошибки:

Код:
template<class TYPE>
PtrList<TYPE>::~PtrList(void)
{
LNode<TYPE> *ptr,*nxt;

[u]if(size&&pthread_mutex_lock(&CS)==EOK)[/u]   // 'size', 'CS' - was not declared in this scope (???)
{
[u]for(ptr=start;ptr;ptr=nxt)[/u]   // 'start' - was not declared in this scope (???)
{
nxt=ptr->next;
delete ptr->body;
delete ptr;
}
size=0;
[u]start=stop=NULL;[/u]   // 'stop' - was not declared in this scope (???)
pthread_mutex_unlock(&CS);
}
[u]pthread_mutex_destroy(&CS);[/u]   // 'CS' - was not declared in this scope (???)
}

Шо за бля?! Учитывая, что ошибок там нет и, к примеру, в VS2008 все компилируется прекрасно (только mutex, естественно, по-другому реализован).
Записан
LP006688
Jr. Member
**
Offline Offline

Сообщений: 76



Просмотр профиля
« Ответ #1 : Июня 26, 2009, 02:38:12 pm »

Сам вопрос задаю, сам отвечаю.

Епта, осьминоги... Для авторов GCC спецификации на C++ не существует -- в порожденном классе пришлось добавлять this-> для всех элементов базового класса.

Уроды.
Записан
lastcross
Full Member
***
Offline Offline

Сообщений: 237


Просмотр профиля
« Ответ #2 : Июня 26, 2009, 05:17:55 pm »

Сам вопрос задаю, сам отвечаю.

Епта, осьминоги... Для авторов GCC спецификации на C++ не существует -- в порожденном классе пришлось добавлять this-> для всех элементов базового класса.

Уроды.

Ну думаю насчет спецификации наверное вы погорячились.
Цитировать
In a template definition, unqualified names will no longer find members of a dependent base (as specified by [temp.dep]/3 in the C++ standard). For example,
Код:
template <typename T> struct B {
  int m;
  int n;
  int f ();
  int g ();
};
int n;
int g ();
template <typename T> struct C : B<T> {
  void h ()
  {
    m = 0; // error
    f ();  // error
    n = 0; // ::n is modified
    g ();  // ::g is called
  }
};
You must make the names dependent, e.g. by prefixing them with this->. Here is the corrected definition of C<T>::h,
Код:
template <typename T> void C<T>::h ()
{
  this->m = 0;
  this->f ();
  this->n = 0
  this->g ();
}

Цитата отсюда:
http://gcc.gnu.org/gcc-3.4/changes.html

З.Ы.: Офтоп, а что за "список" такой? Почему не заюзать СТЛ?
Записан
LP006688
Jr. Member
**
Offline Offline

Сообщений: 76



Просмотр профиля
« Ответ #3 : Июня 26, 2009, 10:24:48 pm »

Цитата: lastcross
Цитата отсюда:
http://gcc.gnu.org/gcc-3.4/changes.html

З.Ы.: Офтоп, а что за "список" такой? Почему не заюзать СТЛ?
Это НЕ пример для моего случая. У меня темплейты не структур (все элементы по умолчанию public), а классов (все элементы по умолчанию private). И наследование не private (как в примере), а public, что есть "две большие разницы". Если авторы GCC распространили это правило и на темплейты классов, игнорируя типы наследования, то они ебалбасы.

Стандартом языка С++ является International Standard ISO/IEC 14882 Second Edition 2003-10-15, и там такого изврата нет. Bjarne Stroustrup тоже ничего об этом нововведении не знает.

Список я сделал свой, что бы не искать багов в чужом коде.
« Последнее редактирование: Июня 26, 2009, 10:35:34 pm от LP006688 » Записан
lastcross
Full Member
***
Offline Offline

Сообщений: 237


Просмотр профиля
« Ответ #4 : Июня 28, 2009, 12:10:31 pm »

Это НЕ пример для моего случая. У меня темплейты не структур (все элементы по умолчанию public), а классов (все элементы по умолчанию private). И наследование не private (как в примере), а public, что есть "две большие разницы". Если авторы GCC распространили это правило и на темплейты классов, игнорируя типы наследования, то они ебалбасы.

Стандартом языка С++ является International Standard ISO/IEC 14882 Second Edition 2003-10-15, и там такого изврата нет. Bjarne Stroustrup тоже ничего об этом нововведении не знает.

Список я сделал свой, что бы не искать багов в чужом коде.

1)И что в том что в примере описана структура? Запостинный мной пример имеет более слабое ограничение по доступу к элементам чем ваш и при этом расскрывает наличие ошибки компиляции. (тоесть все члены паблик, наследование тоже ПАБЛИК - тоесть доступ ожидается везде!, но приэтом GCC указывает что возможна ошибка. У вас члены протектед и наследование паблик - что является более строгим правилом доступа к элементу. Если оведение слабого правила описано, то ожидать иного поведение от более строгого правила не стоит в данном случае). Так же сказано что данное поведение более близко к стандарту.

По поводу стандарта -  в стандарте описаны общие требования правила и спецификации из которых вытекают частные случаии (14.6.2 Dependent names [temp.dep]). Ваш случай - в проблеме поиска имени в шаблонах компилятором. И чтобы избежать неодназначности, нужно либо боращатся к членам базового шлабонного класса через this или же через List<Type>::. Другими словами, вы ведь можете специализировать класс List под конкретный тип, в котором CS может отсутвовать как атрибут или вообще быть типом - компиляция шаблонов в таких случаях не такая простая задача, что соответсвнно требует от программиста конкретных указаний ожидаемых действий.
И то что мелкософт "это" умеет (то поведение которое Вы ожидаете), не означает что есть такие требование в стандарте (еще раз, проблеме не в наследовании класов и ли типе доступа, проблема в случае с наследованием от шаблонного зависимого базового класса!)

Более детально по этому поводу можно почитать здесь: http://www.libray.narod.ru/rapid/c_schablon.htm (9.4.2 стр 161 "Зависимые базовые классы")

По поводу "самописного" списка - он трудно расширяемый. Хотя впринципе опять же - особо к делу не относится.
« Последнее редактирование: Июня 28, 2009, 01:13:27 pm от lastcross » Записан
Страниц: [1]
  Печать  
 
Перейти в: