LINUX.ORG.RU

ошибка линковки из-за шаблонов c++


0

0

Есть шаблонизированный класс A, и есть класс B, у которого шаблонизирована функция f, и эта функция использует объект класса A<T>, если вызвано ее инстанцирование для класса T.

Все это определено в файлах A.h B.h, а в A.cpp и B.cpp тестовые функции. В A.cpp создаются экземпляры A<int>. Так вот, если B.cpp вызывается что-то вроде B::f<int>() -- все ОК, но если в B::f<char>() -- получаю ошибку линковки

g++ -o miptcc ir/bblock.o ir/cfedge.o ir/cfg.o ir/dl_list.o ir/edge.o ir/expr.o ir/gnode.o ir/graph.o ir/ir.o ir/l_list.o ir/pool.o ir/slab_allocator.o ir/stmt.o main.o ir/pool.o(.gnu.linkonce.t._ZN4pool14init_allocatorIcEEvj+0x35): In function `void pool::init_allocator<char>(unsigned)':

/home/tiger/pr/miptcc/ir/pool.cpp:37: undefined reference to `slab_allocator<char>::slab_allocator[in-charge](unsigned)' collect2: ld returned 1 exit status

(slab_allocator = A, pool = B).

Я пытался создать более простой пример данной ситуации, чем проект, однако ничего не вышло: там все линкуется. Может кто сталкивался с подобной ситуацией?

anonymous

IMHO довольно очевидно, что нужна явная специализация.

Напиши где-нибудь template <> class slab_allocator<char>;

anonymous
()

У тебя там чисто случайно partial specialisation для этой функции не
сделан? Вообще, больше кода не помешало бы.

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

это называется не specialization, а explicit instaniation, и пишется template class slab_allocator<char>;

AnToXa
()

дело в том, что при создании A<int> в вашей функции компилятор производит implicit template instaniation, т.е. генерирует код для методов класса A<int>, для всяких там static members и проч. но в то же время компилятор совсем не обязан и, на самом деле, не может сделать instaniation для A<char> и всех остальных типов, которымиможет быть параметризован A.

простое решение - включить определение шаблонного класса в .h, тогда компилятору буддут доступны исходники и он сможет сделать instaniation для slab_allocator<char>.

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

У меня и так шаблонный класс в .h

Может имеется ввиду несколько другое? Да и проблема в том, что классы, которые я пишу, будут использовать другие люди, поэтому нужно, чтобы они просто могли писать, скажем, B::f<TheirClass>(). Может поможет сложное решение?

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

Вот, удалось его упростить. Все include, define и using я убрал. По идее должен выводится всякий мусор, однако выводится та же ошибка линковки.
---------------
slab_allocator.h:
---------------
template <typename type>
class slab_allocator
{
	public:
		type *get_new()
                {return (new type());}
};
---------------
pool.h:
---------------
class pool
{
	public:
		template<typename type>
				void init_allocator()
				{
					cout << (new slab_allocator<type>)->get_new();
				}

};
---------------
slab_allocator.cpp:
---------------
void slab_allocator_test()
{
	cout << (new slab_allocator<int>)->get_new();
}

void pool_test();
int main()
{
	slab_allocator_test();
	pool_test();
}
---------------
pool.cpp:
---------------
void pool_test()
{
	pool p;
	p.init_allocator<char>();
}

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

Ура. Нашел ошибку. Тот код, который я запостил компилится и работает, но вот если определение функции get_new вынести в slab_allocator.cpp -- все перестает работать. Может, кто знает, почему и как от этого избавиться?

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

прочитал в Страуструпе, что это должно лечиться словом export перед определением -- ни черта не помогает.

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

> прочитал в Страуструпе, что это должно лечиться словом export перед
> определением -- ни черта не помогает.

А оно не обязано =)

AFAIR, единственный компилятор, поддерживающий export template - это
Comeau C++. Уж больно нетривиальная это задача. Там по сути приходится
генерировать не объектник, а некий промежуточный вариант, чуть ли не
дамп AST - чтоб потом можно было его инстанцировать для каждой
конкретной специализации.

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

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

export обычно все равно требует полных исходников: http://www.gotw.ca/publications/mill23.htm http://www.gotw.ca/publications/mill24.htm

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