Шаблонирование C ++, передача указателя на функцию с параметризованным типом возврата

0

Я хочу параметризовать возвращаемое значение функции для соответствия возвращаемому значению указателя функции, который я передаю. Раньше я занимался только джоями Java, так что у меня есть хороший шанс, что я здесь что-то совсем не вижу.

функция выглядит так:

<in header>
template <typename T> static T getItems(const char* xpath, T (*getThings)(xpath_node_set*));

<in body>
template <typename T>
T XMLAdapter::getItems(const char* cpath, T(*getThings)(xpath_node_set*)){
    return getThings(head.select_nodes(path));
}

и функция, с которой я перехожу, выглядит следующим образом:

size_t handler(xpath_node_set* in){
    return in->size();
}

И ошибка, которую я получаю:

Error   1   error LNK2019: unresolved external symbol \
"public: static unsigned int __cdecl XMLAdapter::getItems<unsigned int>(char const *,unsigned int (__cdecl*)(class pugi::xpath_node_set *))" (??$getItems@I@XMLAdapter@@SAIPBDP6AIPAVxpath_node_set@pugi@@@Z@Z) \
 referenced in function _wmain  C:\Users\Adam\SkyDrive\Documents\proj\ray\ray\ray.obj   ray

Что дает?

  • 1
    переместить тело функции в заголовок.
  • 0
    Вы определили эту функцию?
Показать ещё 6 комментариев
Теги:
templates
function-pointers

2 ответа

0

удалите static файл из прототипа, он сделает ваш файл функции локальным (т.е. невидимым для других TU).

Как правило, определение шаблона функции должно появляться в заголовке, а не в отдельном файле.cpp.

0

Функции шаблона должны быть полностью реализованы (не просто объявлены) в заголовке, или вы столкнетесь с такими ошибками компоновщика, как если бы ваш вызывающий объект и функция шаблона не были в одном файле.cpp.

Подумайте об этом так: когда вы запускаете компилятор на свой код, вы фактически составляете отдельный.obj файл для каждого файла.cpp. С точки зрения компилятора это полностью независимые черные ящики. Каждый.cpp файл может быть скомпилирован параллельно, и между ними есть нулевые зависимости. Единственными зависимостями являются объявления функций (указанные в заголовках), которые говорят "да, да... кто-то другой это реализует, пусть компоновщик жалуется, если он не может его найти".

Когда у вас есть функция шаблона, то, что вы действительно делаете, - это рецепт того, как сделать функцию. Если у вас есть Foo <T>, и вы хотите вызвать его с помощью int и с помощью строки, в вашем конечном двоичном файле есть буквально две сгенерированные функции, которые полностью символически различаются: Foo <int> и Foo <string>.

Тем не менее, если у вас есть реализация вашей функции шаблона в отдельном файле.cpp у кого-то, кто пытается вызвать специализированную версию, у них нет возможности "готовить" новую версию этой функции с любыми аргументами шаблона, которые они поставляют. Все, что у них есть, это заголовок, в котором говорится: "Foo <T> - это функция, которую кто-то еще реализовал", чтобы успокоить компоновщик. Но ваш TemplateImplementation.cpp не знает, что он должен был сгенерировать Foo <int> и Foo <string>.

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню