LINUX.ORG.RU

[C++ такой C++]Шаблонные методы и разделение на .h/.cpp


0

0

Есть класс с шаблонным методом. Объявление лежит в myclass.h:

#include <iostream>

class MyClass
{
	//Тут поля
public:
	template<typename T> void TemplateMethod(T data);
	//Тут еще методы.
};

Реализация метода в myclass.cpp:

#include "myclass.h"

template<typename T> void MyClass::TemplateMethod(T data)
{
	std::cout << "Data: " << data << std::endl;
}

И в main.cpp:

#include "myclass.h"

int main(int argc, char **argv)
{
	MyClass mc;
	mc.TemplateMethod("test");

	return 0;
}

Линковщик матерится:

/data/home/hetor/Projects/C++/test_Class/main.cpp:6: undefined reference to `void MyClass::TemplateMethod<char const*>(char const*)'

При чем если засунуть реализацию в myclass.h, то все работает. ЧЯДНТ? (Только не говорите, что пишу на плюсах).


если мне не изменяет память ты неверно оформил реализацию, перечитай еще раз про шаблоны

trashymichael ★★★ ()

Не поверишь, но ты сам же и написал, что делаешь не так. Реализация должна быть в заголовочном файле, шаблоны же.

anonymous ()

Шаблоны технически очень сложно скомпилировать в объектник, за исключением специализированных.

SV0L0CH ()

По-моему, такой вопрос уже второй раз за неделю.

Love5an ()

ЧЯДНТ?

не знаешь языка, на котором пишешь

jtootf ★★★★★ ()

Можешь добавить в конец файла myclass.cpp следующую строку и все будет хорошо)

template void MyClass::TemplateMethod<const char*>(const char* data);

shelA ()
Ответ на: комментарий от Attila

> Перекинь #include <iostream> в myclass.cpp, дурила, что оно в *.h делает?

А что оно прохого делает в .h? Оскорбляет твои религиозные чуства?)

shelA ()
Ответ на: комментарий от shelA

Можешь добавить в конец файла myclass.cpp следующую строку и все будет хорошо)

template void MyClass::TemplateMethod<const char*>(const char* data);

Плохой совет. А если он с int-ом попытается метод вызвать? То же самое и для int-ов писать? И для всех остальных типов, с которыми будет вызываться метод? Нафиг это не надо

yoghurt ★★★★★ ()
Ответ на: комментарий от yoghurt

> Плохой совет. А если он с int-ом попытается метод вызвать?

Просто допишет еще одну строчку ))) template void MyClass::TemplateMethod<int>(int data);

Если бы ты внимательно прочитал посыл ТС, то понял бы - он в курсе, что нужно писать реализацию в хидере и то что это лучший вариант. Вопрос был как вынести реализацию из хидера.

shelA ()
Ответ на: комментарий от yoghurt

> В хидерах должно быть по возможности как можно меньше инклудов. Лень объяснять, почему

Ну что мне тебе ответить?) Да лень отвечать?) Ну ты сам все понял!)

shelA ()
Ответ на: комментарий от shelA

>Просто допишет еще одну строчку ))) template void MyClass::TemplateMethod<int>(int data);

Я уже сказал, что это ужасно

Вопрос был как вынести реализацию из хидера

Расово верный путь - export и только export. Только вот он мало кем поддерживается (по крайней мере, так было пару лет назад). Остальное - ересь

yoghurt ★★★★★ ()
Ответ на: комментарий от yoghurt

> В хидерах должно быть по возможности как можно меньше инклудов. Лень объяснять, почему

Я могу объяснить.

Что бы потом когда автор добавит в myclass.h ссылки например на std::ostream корректность подключения myclass.h в myclass.cpp зависила бы от его положения относительно #include <iostream> в myclass.cpp и что бы программист решивший использовать такой не полный заголовочный файл от этого опух, постоянно помня о том что он должен писать #include «myclass.h» только после #include <iostream> и ни в коем случае не до :)

Eshkin_kot ★★ ()
Ответ на: комментарий от Eshkin_kot

>> постоянно помня о том что он должен писать #include «myclass.h» только после #include <iostream> и ни в коем случае не до :)

Сейчас тебе Йогурт объяснит как это ужасно и направит на «Расово верный путь» ;)

shelA ()

на cplusplus.com в сааамом низу ответ.

реализация шаблонного метода должна быть в header'e.

bk_ ★★ ()

Стандартным методом является #include «myclass.cpp» в «myclass.h» (а не наоборот).

Я же говорю, эти шаблоны - это препроцессор такой, только и всего.

Miguel ★★★★★ ()
Ответ на: комментарий от Eshkin_kot

> и что бы программист решивший использовать такой не полный заголовочный файл от этого опух, постоянно помня о том что он должен писать #include «myclass.h» только после #include <iostream> и ни в коем случае не до

Если программист не знает таких элементарных вещей, ему действтиельно лучше опухнуть. :3

LamerOk ★★★★★ ()
Ответ на: комментарий от yoghurt

export и только export

По ссылке на faq:

The future of the export keyword is unknown

some compiler vendors are indicating they might never implement it

Ну и стоит ли с ним связываться?

unsigned ★★★ ()
Ответ на: комментарий от unsigned

С плюсами вообще лучше не связываться. Инфа 100%

yoghurt ★★★★★ ()

эм, я обычно так пишу:

template<typename T> 
void MyClass<T>
    ::TemplateMethod(T data) {
        /* blah-blah */
} 

и всё работает

ЗЫ я правильно понял суть вопроса? (а то я чего-то тут забегался) :)

ЗЗЫ и да, может всё-таки лучше написать не T, а T& или T*?

shty ★★★★★ ()

В современо стандартне С++ от template export отказались (раньше была возможность указать шаблон как экспортируемый из объектника, но так не один компилятор этот эксопрт хорошо не организовал).

Поэтому в точке вызова шаблона необходимо, чтобы было доступно описание шаблона (definition), а не только его объявление (declaration).

Исключение составляют явно-спецаилизированные шаблоны (и то, если их не объявить static)

В общем реализация шаблона в cpp это скорее исключение, чем правила, и, имхо, должно у начинающих программистов караться через тумба-уюмба

namezys ★★★★ ()
Ответ на: комментарий от yoghurt

я очень сомневаюсь, что он мог делать глубокую оптимизацию после подстановки параметров в экспортируемый шаблон

в понятие экспорт входила компиляция, чтоб значительно уменьшить время инстанциации шаблона - но по факту это убивало возможность оптимизации

сначала обсуждали другие стандарты экспорта, а потом вообще от этого отказались.

precompile header решают эту проблему

namezys ★★★★ ()
Ответ на: комментарий от yoghurt

может всё-таки лучше написать не T, а T& или T*?

Смотря где.

конечно здесь:

TemplateMethod(T data)

для POD'ов не страшно, но тут же template, так что может быть и крокодил квадратный с ленточками, лучше написать

А вообще всё уже придумано: http://www.boost.org/doc/libs/1_40_0/libs/utility/call_traits.htm

а это уже следующий этап осознания :)

shty ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.