Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Не разберусь с шаблонами


Автор: PirateTigo 11.8.2008, 09:28
В общем у меня есть шаблон класса, в котором определена функция Save:
Код

template <class T>
class List {
    int N;                            //Number of elements
    Elem<T> *Head;                    //Head of list
public:
//Constructors
    List(void);
    List(T&);

//Methods
    void AddElem (T&, int);            //Additional Elem to List by logical number
    void DelElem (int);                //Delete Elem by logical number
    int Max (int);                    //Search maximum of elements
    int Min (int);                    //Search minimum of elements
    void Sort (void);                //Sorting insets
    Elem<T> *Get (int);                //Get point to Elem by set number
    BOOL Save (char *);                //Save list into the set file

//Operations for work with streams
    friend std::istream &operator>><>(std::istream &,List<T> &);
    
};


Ее реализация лежит в том же файле:
Код

BOOL List<NumString>::Save(char *s)
{
    ...
}


При линковке происходит ошика: 
Код

error LNK2019: unresolved external symbol "class std::basic_istream<char,struct std::char_traits<char> > & __cdecl >>(class std::basic_istream<char,struct std::char_traits<char> > &,class List<class NumString> &)" (?>>@@YAAAV?$basic_istream@DU?$char_traits@D@std@@@std@@AAV12@AAV?$List@VNumString@@@@@Z) referenced in function _main


Подскажите, пожалуйста, что я сделал не так? Заранее благодарен

Автор: Alek86 11.8.2008, 10:26
написано, что не реализован  оператор >>

Автор: PirateTigo 11.8.2008, 11:15
В том то и дело, что он реализован! И когда я комменчу определение и реализацию функции Save, то все линкуется на ура..  smile 

Автор: mes 11.8.2008, 11:18
Цитата(PirateTigo @  11.8.2008,  11:15 Найти цитируемый пост)
В том то и дело, что он реализован! 

можно код? 

Автор: PirateTigo 11.8.2008, 11:23
Код

можно код?


Пожалуйста:

[/code]
Код

template <class T>
std::istream &operator>>(std::istream& IO, List<T> &Spisok)
{//IO - input stream, Spisok - List of objects
    T Obj;
    IO >> Obj;
    Spisok.AddElem(Obj,0);
    return IO;
}


Автор: mes 11.8.2008, 12:24
Цитата(PirateTigo @  11.8.2008,  11:23 Найти цитируемый пост)
Пожалуйста:

надеюсь она тоже в хидере ?

Автор: Alek86 11.8.2008, 12:27
Код
operator>><>

что тут <> означает?

Автор: PirateTigo 11.8.2008, 12:28
Цитата(mes @ 11.8.2008,  12:24)
надеюсь она тоже в хидере ?

Весь код лежит в одном файле "List.h"

Добавлено через 2 минуты и 28 секунд
Цитата(Alek86 @ 11.8.2008,  12:27)
что тут <> означает?

http://forum.vingrad.ru/forum/topic-223092/kw-%D0%BB%D0%B8%D0%BD%D0%BA%D0%B5%D1%80-lnk-2019-operator-friend.html

Вот старая тема, тут все освещено

Автор: Alek86 11.8.2008, 12:37
не знаю, где ты это правило взял

напиши (прям в классе) так
Код

  //Operations for work with streams
  friend std::istream &operator>>(std::istream& IO, List<T> &Spisok)
  {//IO - input stream, Spisok - List of objects
    T Obj;
    IO >> Obj;
    Spisok.AddElem(Obj,0);
    return IO;
  }

и не мучься

Автор: PirateTigo 11.8.2008, 12:53
Цитата(Alek86 @ 11.8.2008,  12:37)
не знаю, где ты это правило взял

Вот здесь взял:
http://www.parashift.com/c++-faq-lite/templates.html#faq-35.16

Сделал как ты сказал, все работает, но все же это не решение проблемы, я думаю...

Автор: Alek86 11.8.2008, 13:11
Цитата(PirateTigo @  11.8.2008,  12:53 Найти цитируемый пост)
но все же это не решение проблемы, я думаю...

почему ты так думаешь?
ты реализовал друга прямо в классе

Добавлено @ 13:13
кстати говоря, в твоем случае friend не нужен - вынеси ф-ю из класса

Автор: PirateTigo 11.8.2008, 13:28
Ок, тема закрыта, всем спасибо..  smile 

Автор: UnrealMan 11.8.2008, 16:18
Цитата(Alek86 @  11.8.2008,  13:27 Найти цитируемый пост)
что тут <> означает?

Это называется "тупо изменяем код до тех пор, пока не начнёт компилироваться". А то, что компилироваться при этом будет не корректная с точки зрения языка программа, а полная чушь - дело десятое  smile 

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

Код

template <class T>
    class List;

template <class T>
    std::istream &operator>>(std::istream& IO, List<T> &Spisok);

Автор: PirateTigo 11.8.2008, 20:32
Цитата(UnrealMan @ 11.8.2008,  16:18)
Это называется "тупо изменяем код до тех пор, пока не начнёт компилироваться". А то, что компилироваться при этом будет не корректная с точки зрения языка программа, а полная чушь - дело десятое

Я вверху дал ссылку, где об "этом" подробно написано!

Так что, не нужно обвинять меня в безрассудстве действий!

Автор: Alek86 11.8.2008, 22:36
Цитата(PirateTigo @  11.8.2008,  20:32 Найти цитируемый пост)
Так что, не нужно обвинять меня в безрассудстве действий!

вообще-то он по делу говорит
и в приведеной тобой ссылке то же самое написано, что и у него

Автор: PirateTigo 13.8.2008, 19:22
Цитата(Alek86 @ 11.8.2008,  22:36)
и в приведеной тобой ссылке то же самое написано, что и у него

Вообще-то там приводится три выхода из ситуации, один из них мой. Поэтому не правда, что я сделал не подумав.

Автор: UnrealMan 13.8.2008, 20:50
Цитата(PirateTigo @  13.8.2008,  20:22 Найти цитируемый пост)
Вообще-то там приводится три выхода из ситуации, один из них мой. Поэтому не правда, что я сделал не подумав. 

Ответь на пару вопросов:

1) что в твоём примере делает следующая строчка?

friend std::istream &operator>><>(std::istream &,List<T> &);

2) Что в этой строчке означает <>?


Автор: PirateTigo 15.8.2008, 04:53
Цитата(UnrealMan @ 13.8.2008,  20:50)
1) что в твоём примере делает следующая строчка?

friend std::istream &operator>><>(std::istream &,List<T> &);

2) Что в этой строчке означает <>?

Я не отвечаю на 100%, что это так. Так как сам ничего об этом раньше не слышал. Но раз в статье написано, что это решает проблему, то почему бы и не использовать эту "magic stuff" <>. И в той статье описано, что именно происходит, когда компилятор видит <>:
"After the compiler sees that magic stuff, it will be better informed about the friend functions. In particular, it will realize that the friend lines are referring to functions that are themselves templates. That eliminates the confusion." Мне этого описания вполне достаточно для того, чтобы использовать <> в своей программе, и то что я не нашел лучшего вовсе не означает, что я сделал это наобум.

Автор: UnrealMan 15.8.2008, 12:08
Я вот только не понял, откуда ты тогда сделал вывод, что

Цитата(PirateTigo @  4.8.2008,  15:13 Найти цитируемый пост)
Оказывается при объявлении дружественных шаблонов функций для шаблона класса нужно либо заранее объявлять прототипы класса и функции, либо писать <> после названия функции.
?
Почему "либо", когда предварительное объявление шаблона функции просто обязано присутствовать, если ты пишешь

Код

friend std::istream &operator>><>(std::istream &,List<T> &);
?

Автор: PirateTigo 19.8.2008, 12:57
Ну не знаю, как я понял, потому что использование <> - это тоже самое для шаблона френд функции, что и extern для какой-нибудь внешней переменной. Если не так, то поправь меня.

Автор: Alek86 19.8.2008, 13:23
Цитата(PirateTigo @  19.8.2008,  12:57 Найти цитируемый пост)
Если не так, то поправь меня.

как тебя можно поравить, если уже 10 раз было сказано, как нужно писать правильно, а ты все равно стоишь на своем?
можно только сказать РТФМ (в частности, "Шаблоны C++")

Автор: bsa 19.8.2008, 14:23
PirateTigo
Цитата
The solution is to convince the compiler while it is examining the class body proper that the operator+ and operator<< functions are themselves templates. There are several ways to do this; one simple approach is pre-declare each template friend function above the definition of template class Foo: 
Код
 template<typename T> class Foo;  // pre-declare the template class itself
 template<typename T> Foo<T> operator+ (const Foo<T>& lhs, const Foo<T>& rhs);
 template<typename T> std::ostream& operator<< (std::ostream& o, const Foo<T>& x); 

Also you add <> in the friend lines, as shown: 
Код
 #include <iostream>
 
 template<typename T>
 class Foo {
 public:
   Foo(const T& value = T());
   friend Foo<T> operator+ <> (const Foo<T>& lhs, const Foo<T>& rhs);
   friend std::ostream& operator<< <> (std::ostream& o, const Foo<T>& x);
 private:
   T value_;
 }; 
After the compiler sees that magic stuff, it will be better informed about the friend functions. In particular, it will realize that the friend lines are referring to functions that are themselves templates. That eliminates the confusion.
Свободный перевод особо важных мест в двух словах: первый метод заключается в предопределении шаблонных функции до описания шаблонного класса Foo... а так же (also - переводится как "а так же") добавлении <> в объявление дружественных шаблонных функций.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)