Гадкая фигня с шаблоном((

Тема в разделе "LANGS.C", создана пользователем Necromancer13, 31 мар 2010.

  1. Necromancer13

    Necromancer13 Виталий

    Публикаций:
    0
    Регистрация:
    26 окт 2007
    Сообщения:
    202
    Адрес:
    Украина, Берегово
    Доброго времени суток) Помогите, пожалуйста.
    Я вот сейчас читаю про шаблоны С++, но у меня не компилится пример..

    // main.cpp
    Код (Text):
    1. #include <iostream>
    2. #include "grid.h"
    3.  
    4. using namespace std;
    5.  
    6. int main(int argc, char** argv)
    7. {
    8. Lab<int> b;
    9. getchar();
    10. return 0;
    11. }
    // grid.h
    Код (Text):
    1. template <typename>
    2. class Lab
    3. {
    4. public:
    5. Lab();
    6. int x;
    7. };
    // grid.cpp
    Код (Text):
    1. #include <iostream>
    2. #include "grid.h"
    3.  
    4. template <typename>
    5. Lab<t>::Lab()
    6. {
    7. std::cout << "OOO!" << std::endl;
    8. }
    При компиляции пишет:
    [Linker error] undefined reference to `Lab<int>::Lab()'

    Почему?

    Кстати, а если конструктор встроенным сделать, то все работает. как так?
     
  2. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    1. Определение шаблона убрать из .cpp

    2. template <typename>
    Lab<t>::Lab() - wtf?

    может быть

    template <typename t>
    Lab<t>::Lab() ?
     
  3. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    Necromancer13
    Код (Text):
    1. #include <iostream>
    2. #include "grid.h"
    3.  
    4. template <typename t>
    5. Lab<t>::Lab()
    6. {
    7. std::cout << "OOO!" << std::endl;
    8. }
     
  4. found

    found New Member

    Публикаций:
    0
    Регистрация:
    30 мар 2010
    Сообщения:
    5
    Лишь интеловский компилятор поддерживает раздельную линковку шаблонов, так что просто поместите тело функции из cpp файл в заголовочный.
    Код (Text):
    1. #include <iostream>
    2.  
    3. template <typename>
    4. class Lab
    5. {
    6. public:
    7. Lab();
    8. int x;
    9. };
    10.  
    11. template <typename t>
    12. Lab<t>::Lab()
    13. {
    14. std::cout << "OOO!" << std::endl;
    15. }
     
  5. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    >[Linker error] undefined reference to `Lab<int>::Lab()'
    >Почему?

    Поскольку при компиляции файла 'main.cpp' не видно шаблонного определения Lab::Lab(), функция Lab<int>::Lab() считается внешней (определённой в другом модуле). Однако при компиляции файла 'grid.cpp' компилятор не видит обращений к функции Lab<int>::Lab() – и поэтому не создаёт такую функцию. Как уже посоветовал found, можно поместить определение в заголовочный файл, либо можно явно сказать компилятору о необходимости инстанциации Lab<int>::Lab().

    // grid.cpp
    Код (Text):
    1. #include <iostream>
    2. #include "grid.h"
    3.  
    4. template <typename t>
    5. Lab<t>::Lab()
    6. {
    7. std::cout << "OOO!" << std::endl;
    8. }
    9.  
    10. // template Lab<int>::Lab();     // инстанциировать только одну функцию для 'int'
    11. template class Lab<int>;         // инстанциировать весь класс для 'int'
     
  6. Necromancer13

    Necromancer13 Виталий

    Публикаций:
    0
    Регистрация:
    26 окт 2007
    Сообщения:
    202
    Адрес:
    Украина, Берегово
    Большое спасибо! :) действитель при помещении определений методов в заголовочный файл работает. Я просто думал почему-то, что все определения методов следует подключать в исходный файл :)
     
  7. found

    found New Member

    Публикаций:
    0
    Регистрация:
    30 мар 2010
    Сообщения:
    5
    Чтобы не плодить тем, попробую здесь спросить по шаблонам, заметил, что в VS 2010 код правильный по стандарту:
    Код (Text):
    1. template<class OperandType,class ElPartType>
    2. class Ellement
    3. {
    4. public:
    5.         ...
    6.         friend std::ostream& operator<< <>(std::ostream&,const Ellement&);
    7. };
    компилируется лишь при явном указании:
    Код (Text):
    1. using namespace std;
    Иначе:
    error C2143: syntax error : missing ';' before '<' see reference to class template instantiation 'Ellement<OperandType,ElPartType>' being compiled
    error C2433: '<<' : 'friend' not permitted on data declarations
    error C2530: '<<' : references must be initialized
    error C2238: unexpected token(s) preceding ';'

    В чем может быть проблема? И на что в данном случае так сильно влияет using namespace?

    Полный текст модуля: http://code.google.com/p/blockschemstudio/source/browse/trunk/RPN/Ellement.h
     
  8. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    ?
    friend std::ostream& std::operator<< <>(std::ostream&,const Ellement&);
     
  9. found

    found New Member

    Публикаций:
    0
    Регистрация:
    30 мар 2010
    Сообщения:
    5
    О! спасибо огромное :)
     
  10. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    found
    А откуда собственно взялось <> применительно к operator<< ?
     
  11. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    кстати, имхо, код не соответствует стандарту...
     
  12. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    ... и похоже, в таком виде:
    компилируется только 10-й студией :):):)
    А почему не закодить по-человечески?
     
  13. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    found
    Тю! Шо вы меня внатуре запутали!
    Код (Text):
    1. template<class, class> class Ellement;
    2. template<class OperandType,class ElPartType> std::ostream& operator<<(std::ostream&,const Ellement<OperandType,ElPartType>&);
    3.  
    4. template<class OperandType,class ElPartType>
    5. class Ellement
    6. {
    7. public:
    8.         ...
    9.         friend std::ostream& operator<< <>(std::ostream&,const Ellement&);
    10. };
    где-то так...

    Booster
    Ну, я не знаю, как работает это шаманство, но я бы так делать не стал. Судя по всему в 10-ке где-то объявлен глобальный шаблон типа template<class T> ostream& operator<<(ostream&, T); но в общем случае стандарт это не гарантирует, если я правильно помню 27.6.2.5 :)

    p.s. а я бы все-равно написал бы по-другому ;)
     
  14. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    тля... верните, блин, редактирование :dntknw:
    вместо
    следует читать