Неиспользуемые функции шаблона в общей библиотеке - PullRequest
2 голосов
/ 05 августа 2010

У меня есть шаблонная функция в общей библиотеке, написанная на C ++ (функция не вызывается нигде в библиотеке, поэтому ее не следует генерировать, я не прав?) [G ++, Linux]

Я пытаюсь использовать эту функцию шаблона в приложении, но компилятор выдает ошибку ссылки. Я искал функцию с помощью objdump, но не могу увидеть функцию в .so Есть ли способ решить эту проблему?

Ответы [ 5 ]

7 голосов
/ 05 августа 2010

Функции шаблона принадлежат заголовкам библиотеки, они не компилируются в общей библиотеке DLL.Итак, переместите все функции шаблона в заголовок и включите этот заголовок в свое приложение.

6 голосов
/ 05 августа 2010

Самый простой способ - просто переместить весь код шаблона в заголовочный файл (как описано в других ответах)
НО это не единственное решение.

Шаблон нефактические функции.

Шаблон становится функцией, когда есть экземпляр функции.Это может быть сделано неявно или явно.Каждый раз, когда функция используется, происходит неявное воплощение.Но вы также можете явно создать экземпляр функции-шаблона.

Таким образом, вы должны иметь возможность ссылаться на любую экземплярную версию функции-шаблона в вашей общей папке lib.

Заголовочный файл, поэтому мы соблюдаем одно определение.rule.

// tt.h
template<typename T>
int doStuff(Tconst &t);

Исходный файл:

// tt.cpp
#include "tt.h"
template<typename T>
int doStuff(Tconst &t)
{
    return 4;
}

void plop()
{
    int x = 6;
    // implicit instanciation of doStuff<int>(int const&);
    doStuff(x);
}

// explicit instanciation of template
template int doStuff<float>(float const&);

Если бы я скомпилировал вышеизложенное в общую библиотеку.
Тогда было бы доступно два метода doStuff ().

  • doStuff (int const &) // Неявная реализация
  • doStuff (float const &) // Explit instance

g ++ -shared -o tt.so tt.cpp

Теперь, если у нас есть отдельный файл, который мы связываем с общей библиотекой:

// main.cpp
#include "tt.h"

int main()
{
    doStuff(5);   // doStuff<int>()
    doStuff(6.0f); // doStuff<float>()
}

g ++ main.cpp t.so

Компилируется нормально, хотя main не видит код шаблона.

1 голос
/ 05 августа 2010

Шаблоны сложно реализовать разработчикам компиляторов, и поэтому большинство компиляторов C ++ фактически требуют, чтобы вы помещали код шаблона в заголовочные файлы, даже в полные реализации классов (хотя есть некоторые исключения и приемы, чтобы этого избежать).

В вашем случае все, что вам нужно сделать, это переместить шаблон функции в файл заголовка (возможно, с другими шаблонами функций) и импортировать его, когда вам это нужно.

Надеюсь, это поможет.

0 голосов
/ 05 августа 2010

Я попал в ту же ситуацию некоторое время назад, поэтому я исследовал это.В основном шаблоны не создают никакого объектного кода, они просто являются определением для компилятора.Когда вы создаете экземпляр объекта типа std::list<Foo> l, компилятор выдаст как экземпляр, так и специальный код для списка объектов Foo.

Это приводит к двум последствиям:

  • Это не такможно записать код классов шаблонов в выделенный файл .cpp (как вы это сделали бы для обычного модуля), поскольку вы заранее не знаете, какие типы данных вам нужно создать;
  • Два.Файлы cpp, использующие std::list<Foo> в качестве типа данных, создадут копию одного и того же исполняемого кода.

Второй момент затрудняет работу на этапе компоновки, поскольку предполагается, что компоновщик имеет дело с двойными определениями.Возможной стратегией связывания будет сохранение копии для каждого объектного кода.Разумный компоновщик может попытаться оптимизировать вещи, но это создает большую сложность.

Я думаю, именно поэтому gcc так долго компилирует C ++, а с C. намного быстрее, * C. 1015 *

0 голосов
/ 05 августа 2010

Функция, которую вы хотите использовать, должна где-то создаваться, либо в вашей библиотеке, либо в вашем коде.Ваш компилятор должен генерировать для вас экземпляр в программном коде, если прототип не был объявлен как extern.Похоже, вы хотите явно создать экземпляр функции в вашей библиотеке.В один из исходных файлов вашей библиотеки вы можете просто добавить строку, например:

шаблон return_type имя_функции (param_type, param_type);

и код функции должен быть явно сгенерирован.

Подробнее о явной реализации: http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/explicit_instantiation.htm

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