Почему вызов глобальной функции в статической вспомогательной функции класса шаблона приводит к ошибкам компоновщика, а не к вызовам в нестатических функциях-членах?

У меня есть проект, который использует систему сборки autotools для создания статической библиотеки. Я хочу протестировать эту библиотеку, создав небольшую тестовую программу, которая ссылается на нее.

Тестовая программа создается в IDE code :: blocks. Пути, содержащие заголовки, были добавлены в каталоги поиска и добавлена ​​включенная библиотека.

Когда я компилирую свою тестовую программу, я получаю следующую ошибку:

obj/Debug/main.o: In function `givens':
<snip> undefined reference to `xhypot(double, double)'

Тем не менее, xhypot является глобальной функцией, объявленной во включенном заголовке в real.h как:

nr_double_t xhypot (const nr_double_t, const nr_double_t);

и определен в сопутствующем файле real.cpp,

nr_double_t xhypot (const nr_double_t a, const nr_double_t b) {
nr_double_t c = fabs (a);
nr_double_t d = fabs (b);
if (c > d) {
nr_double_t e = d / c;
return c * sqrt (1 + e * e);
}
else if (d == 0)
return 0;
else {
nr_double_t e = c / d;
return d * sqrt (1 + e * e);
}
}

Тип nr_double_t определен в config.h как:

/* The global type of double representation. */
#define nr_double_t double

Где оскорбительный звонок xhypot происходит в статической вспомогательной функции для класса шаблона, например, так:

static nr_double_t
givens (nr_double_t a, nr_double_t b, nr_double_t& c, nr_double_t& s) {
nr_double_t z = xhypot (a, b);
c = a / z;
s = b / z;
return z;
}

Тем не мение, xhypot также вызывается в других нестатических функциях-членах класса с точно таким же синтаксисом (т.е. xhypot(double,double) и если я заменю линию nr_double_t z = xhypot (a, b); в этом статическом методе с линией nr_double_t z = 0.0; ошибка исчезает.

Вот вся моя тестовая программа:

#include "config.h"#include "m_trsolver.h"
int main (int argc, char ** argv)
{

char infile[] = "test.net";
m_trsolver the_m_trsolver;;

return 0;

}

И полный журнал сборки:

g++ -Wall -DHAVE_CONFIG_H  -g    -I../qucs/qucs-core -I../qucs/qucs-core/src -I../qucs/qucs-core/src/components -I../qucs/qucs-core/src/components/devices -I../qucs/qucs-core/src/components/digital -I../qucs/qucs-core/src/components/verilog -I../qucs/qucs-core/src/components/microstrip -I../qucs/qucs-core/src/converter -I../qucs/qucs-core/src/m-interface -I../qucs/qucs-core/src/math  -c /home/s0237326/src/qucs_m_interface_test/main.cpp -o obj/Debug/main.o
/home/s0237326/src/qucs_m_interface_test/main.cpp: In function ‘int main(int, char**)’:
/home/s0237326/src/qucs_m_interface_test/main.cpp:10: warning: unused variable ‘infile’
g++ -L../qucs/qucs-core -L../qucs/qucs-core/src -L../qucs/qucs-core/src/components -L../qucs/qucs-core/src/components/devices -L../qucs/qucs-core/src/components/digital -L../qucs/qucs-core/src/components/verilog -L../qucs/qucs-core/src/components/microstrip -L../qucs/qucs-core/src/converter -L../qucs/qucs-core/src/m-interface -L../qucs/qucs-core/src/math  -o bin/Debug/qucs_m_interface_test obj/Debug/main.o    ../qucs/qucs-core/src/libqucsatorfull.a
obj/Debug/main.o: In function `givens':
/home/s0237326/src/qucs_m_interface_test/../qucs/qucs-core/src/eqnsys.cpp:1341: undefined reference to `xhypot(double, double)'
obj/Debug/main.o: In function `main':
/home/s0237326/src/qucs_m_interface_test/main.cpp:11: undefined reference to `m_trsolver::m_trsolver()'
/home/s0237326/src/qucs_m_interface_test/main.cpp:13: undefined reference to `m_trsolver::~m_trsolver()'
collect2: ld returned 1 exit status
Process terminated with status 1 (0 minutes, 0 seconds)
3 errors, 1 warnings

Я использую code :: blocks 10.05 в Scientific Linux 6.1 с gcc 4.4.6 и передаю -DHAVE_CONFIG_H, так как есть много

#if HAVE_CONFIG_H
# include <config.h>
#endif

В источниках, с config.h генерируется автоконф. Я должен также добавить, что код компилируется нормально при сборке в виде программы. Я извлек подмножество кода для этой программы (все, кроме одного файла) для помещения в эту статическую библиотеку.

Шаблон класса распространяется на два файла, eqnsys.h а также eqnsys.cpp, Я знаю, что это не лучшая практика, это, вероятно, было сделано, поскольку оно довольно большое. Это не мой код. eqnsys.cpp включен в нижней части eqnsys.h ( #include "eqnsys.cpp"). Статическая вспомогательная функция определена в eqnsys.cpp, real.h является #includeЭд на вершине eqnsys.cpp но нет eqnsys.h в случае, если это актуально. Добавление следующего в начало eqnsys.cpp:

template class eqnsys<nr_complex_t>;
template class eqnsys<nr_double_t>;

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

1

Решение

Основываясь на командной строке сборки, вы только компилируете main.cpp и вы не связываете какие-либо библиотеки. Вы должны связать библиотеку, которая содержит недостающие символы, или скомпилировать их источники в свой исполняемый файл.

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

0

Другие решения

Это почти наверняка проблема создания экземпляра шаблона из-за того, что код вашего шаблона находится в .cpp, а не в .h.
Либо переместите свой код в заголовок — чтобы, когда это требуется компилятору, он мог создать экземпляр шаблона для типа, требуемого на лету, или оставить код в .cpp, но принудительно создать экземпляр шаблона (в верхней части файла .cpp) для шаблон arg вам нужно, добавив. Например:

// Explicite template instantiations
#pragma warning(disable: 4660) // For template-class specialization is already instantiated.
template class MyTemplateClass<MyTemplateParamClass>;
0

По вопросам рекламы [email protected]