2013-08-02 2 views
2

У меня есть модуль Apache (.so), который содержит класс, который я пытаюсь полностью отделить от самого Apache. Самый большой источник разочарования - это журнал отладки. Я хочу, чтобы передать функцию регистрации в класс через параметры шаблона. Я могу получить доказательство концепции, чтобы работать хорошо, когда все находится в той же единице трансляции, но он падает, как только они не потому, что функция регистрации является «неопределенная ссылка»:Использовать произвольные функции в качестве аргументов параметров шаблона

/tmp/ccPdPX2A.o: In function `main': 
test.cpp:(.text+0x81): undefined reference to `void C::DoThis<&(LogIt(char const*, ...))>()' 
collect2: ld returned 1 exit status 

Это также происходит, когда Apache пытается загрузить модуль, содержащий класс. ниже код воспроизводит проблему:

// main.cpp 
#include <iostream> 
#include "C.h" 

void LogIt(const char*, ...) 
{ 
    std::cout << "GADZOOKS!\n"; 
} 

int main(int argc, char* argv[]) 
{ 
    C c; 

    c.DoThis<LogIt>(); 
} 


// C.h 
typedef void (*LogFunction)(const char*, ...); 

class C 
{ 
public: 
    template <LogFunction L> 
    void DoThis(); 

    template <LogFunction L> 
    void DoThat(); 
}; 

// C.cpp 
#include "C.h" 

template <LogFunction L> 
void C::DoThis() 
{ 
    L("DoThis!"); 
    DoThat<L>(); 
} 

template <LogFunction L> 
void C::DoThat() 
{ 
    L("DoThat!"); 
} 

Я предпочел бы не прибегнуть к наличию функции передается в качестве параметра функции, т.е.

template <typename F> 
void C::DoThis(F f) 
{ 
    f("DoThis!"); 
} 

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

Можно ли это сделать?

+0

Я не уверен, как этот другой вопрос имеет какое-либо отношение к тому, что я прошу. – James

+0

Являются ли оба определения «LogIt' (' main.cpp') и 'C :: DoThis' (' C. cpp') в том же .so? – willj

+0

@willj Да, они попадают в то же самое .so – James

ответ

1

Хорошо я воссозданы все,

Эта ошибка undefined reference to void C::DoThis<&(LogIt(char const*, ...))>() объясняется here

Теперь, если вы #include "C.cpp" ссылкой выше, это приведет к

undefined reference to void C::DoThat<&(LogIt(char const*, ...))>()

Так исправить:

template <LogFunction L> 
void C::DoThat() //Notice :: used here 
{ 
    L("DoThat!"); 
} 

и все соблюдает и исполняет!

0

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

Либо переместите определения шаблонов в заголовки, либо создайте синтаксис в C.c. Для этого вам нужно будет предоставить декларацию LogIt в C.c.

0

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

Смежные вопросы