LINUX.ORG.RU

Класс с шаблоном и вынос в отдельный объектник

 ,


0

3

Собственно, если в supershitclass.hpp объявить класс с шаблоном, а потом в supershitclass.cpp определить все функции (ну разумеется инклуднув заголовочный), компильнуть в объектник, но потом при линковке, пишет, что эти функции не определены. Это можно как-то побороть или так нельзя? :(

Всегда ваш — волшебник Рукожоп!



Последнее исправление: CYB3R (всего исправлений: 1)

Вы не понимаете, как работают шаблоны.
Почитайте про такие слова как инстанцирование шаблона и что в этот момент происходит.

В вашем случае можно вынести всю реализацию в hpp.

trex6 ★★★★★
()

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

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

Ну я до этого догадывался, подсознательно, что оно типо смотрит в каких типах шаблон юзают и много раз это «переписывает» с этими типами (ну по простому), просто вдруг есть что-то более умное, чем просто всё запихнуть в .hpp :)

Google-ch
() автор топика
Ответ на: комментарий от Google-ch

Насколько я понимаю принцип работы шаблонов, убрать это из hpp в cpp не получится. Когда вы пишите шаблонный класс, на самом деле класс на создается. Создается только заготовка. Т.е. ваш шаблонный код из cpp в объектных файлах вообще отсутствует, если в этом же файле не создается реальный класс.

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

А почему мой g++ это не умеет? :( Или он ещё не весь c++11 умеет?

Google-ch
() автор топика
Ответ на: комментарий от trex6

извиняюсь - плохо прочитал исходный пост, да, тут единственный вариант сделать как предлагает Alv, но это конечно тоже не то

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

Я давно так не делаю, но ЕМНИП:

//A.hpp
...
template <typename T> class A{
...
    void f();
...
};
...
//A.cpp
#include "A.hpp"
...
template <typename T> void A<T>::f(){...}
...
A<int> a_int;
A<double> a_double;
A<float> a_float;

A<char> в этом случае работать не будет. За подробности не поручусь, надо пробовать. Вообще это зависит от деталей реализации компайлера.

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

Пусть в 1.cpp у меня код шаблонной функции, я её использую её в 2.cpp. Для компиляции 2.cpp мне всё равно понадобится 1.cpp? Или не специализированный шаблон непостижимым образом содержится в объектнике?

Я выкинул кресты и томик Александреску ещё до появления этих новшеств, не в курсе.

imtw
()
Ответ на: комментарий от Google-ch

А Вы хотели чудес? Их не бывает... компиляция раздельная, откуда при компиляции модуля A.o (в котором лишь и известны тела методов) компайлер будет знать с какими аргументами инстацируются шаблоны в модуле B.o?

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

ЕМНИП коллеги когда то выносили тела шаблонных ф-й в отдельный файл и инклюдили его как хидер. Профит в том, что не надо продираться через детали реализации когда смотришь хидер. Ну и понатыкав костылей можно ускорить компиляцию.

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

Похоже на хак. Теоретически, оптимизирующий компилятор может заметить, что a_int и т.д. не используются, и выкинуть их? В результате в объектнике не будет нужных функций. Что стандарт говорит?

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

Он просто перепутал с предварительным объявлением шаблонов, которые потом всё равно придётся определить в коде, которому потребуется вызвать шаблонную функцию или создать объект шаблонного класса.

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

А Вы хотели чудес? Их не бывает...

export template или как-то так. Но это почти никто не поддерживает.

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

Вы немного перепутали:

.cpp:

template class A<int>;
template class A<double>;
template class A<float>;

Да, так код для конкретных специализаций попадёт в объектник и к нему можно будет прилинковаться.

Далее, как уже сказали, вынести код из .cpp в заголовочник с шаблоном по понятным причинам, чтобы компилятор мог генерировать код для произвольных параметров шаблона.

И ещё далее, чтобы ускорить компиляцию «тяжёлых» заголовочников их можно прекомпилировать, man gcc -x c++header и gcc -include (-include-pch для clang).

Dendy ★★★★★
()
Последнее исправление: Dendy (всего исправлений: 1)
Ответ на: комментарий от AIv

В стандарте есть для этого ключевое слово export. Правда поддерживается только одним компилятором — comeau.

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

И ещё далее, чтобы ускорить компиляцию «тяжёлых» заголовочников их можно прекомпилировать, man gcc -x c++header и gcc -include (-include-pch для clang).

Не знаю как для clang, а в gcc pch дает максимуму +20% к скорости компиляции. Проверял на своем тяжелом проекте с бустом и прочей шаблонной плюсовой лапшой.

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

Reset

В стандарте есть для этого ключевое слово export.

Уже нет.

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

Объявление переменной - костыль.

Потому не

A<int> a_int;

а на выбор:

template class A<int>;

или

extern template class A<int>;

Называется явное инстанцирование.

Pavval ★★★★★
()
Последнее исправление: Pavval (всего исправлений: 1)
Ответ на: комментарий от Reset

Не знаю как для clang, а в gcc pch дает максимуму +20% к скорости компиляции. Проверял на своем тяжелом проекте с бустом и прочей шаблонной плюсовой лапшой.

Ваша правда. Только что отключил PCH для своего проекта. При сборке в один поток:

without pch: real 8m19.657s
with pch: real 6m29.967s

Завтра приедет 24 Gb RAM для моего десктопа, переведу директорию сборки в tmpfs. Ибо подозрения, что на разбор ~100Mb PCH-файла приходится ресурсов сравнимо с компиляцией. Параллельно читаю документацию по ccache.

Что характерно, на MSVC прирост скорости при PCH помню был заметно лучше. Будет время — выплюну статистику.

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

И потролли потом разрабов gcc (с прямой трансляцией на ЛОР) - мож чё интересное всплывет.

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

В C++11 можно удобно устранять множественную инстанциацию из различных единиц компиляции. В ранних черновиках вроде как были мечты о некоем суперспособе собирать шаблоны в промежуточный язык так, что их уже скомпилированных можно было бы переинстанциировать по другим параметрам, но, насколько я понимаю, разработчики компиляторов это заветировали из-за неоправданной сложности реализации. http://en.wikipedia.org/wiki/C++11#Extern_template

elfy
()

Было в стандарте такое волшебное ключевое слово export, но так как его практически никому из разработчиков компиляторов реализовать не удалось, из последнего стандарта его вообще выпилили.

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