LINUX.ORG.RU

C++: Сгенерировать код из шаблона в объектный файл


0

2

Пусть есть шаблонная функция:

template <typename T> void foo();

И есть множество её специализаций под каждый тип. Как правило их выносят в inline-функции, но в моём случае они получаются большими и раздувать код не хотелось бы. Отсюда вопрос: как правильно сгенерировать объектный код для всех желамых специализаций?

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

Хотелось бы понять, есть ли стандартный способ добиться того же и без побочных эффектов? Как это решается в С++11?

★★★★★

Отсюда вопрос: как правильно сгенерировать объектный код для всех желамых специализаций?

явное инстанцирование

А вообще, не надо так делать. Если большой заголовок, выдели реализацию в _impl.h

annulen ★★★★★
()
//templates_foo.cpp
template <typename T>
void foo()
{
}

template void foo<int>();
template void foo<double>();
$ g++ -Wall -c templates_foo.cpp 
$ nm templates_foo.o|c++filt
00000000 W void foo<double>()
00000000 W void foo<int>()
$ 

А что это за заглушка?

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

Размер заголовочного файла меня не смущает. Проблема в раздувании сегмета кода там, где это не нужно. К примеру, если метод инстанцируется из 100 разных мест, то компилятор размножит его 100 раз встраивая в каждый вызов. Поскольку каждая специализация достаточно объёмная, естественное желание вынести её в отдельный объектник со своей точкой вызова.

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

Может есть какой-нибудь анти-inline ключ или атрибут в GCC для шаблонов?

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

Можно попробовать -ffunction-sections -fdata-sections и -Wl,--gc-sections

Может есть какой-нибудь анти-inline ключ

конечно, в man gcc все есть

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

Спасибо! Пользовался таким кодом пару лет назад в одном проекте, но без практики всё из памяти стирается. Сейчас попробую.

Заглушка была в виде:

typedef void (*foo_int)(int); extern foo_int foo_int_func() { return foo<int>; }
typedef void (*foo_double)(double); extern foo_double foo_double_func() { return foo<double>; }
Dendy ★★★★★
() автор топика
Последнее исправление: Dendy (всего исправлений: 1)
Ответ на: комментарий от annulen

Спасибо за ключи, буду RTFM.

Dendy ★★★★★
() автор топика
27 января 2013 г.
Ответ на: комментарий от Dendy

а слушай я не так немного понял что тебя нужно

Может есть какой-нибудь анти-inline ключ или атрибут в GCC для шаблонов?

__attribute__((noinline)) int void foo(){}
Ну я думаю ты в курсе.

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

Спасибо за наводку. Как будет снова повод почитаю мануал GCC.

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