2013-08-02 72 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.中强制实例化。你必须在C.c中提供LogIt声明。

0

您需要将模板定义放在与声明的位置相同的位置。这意味着您需要将LogIt函数放在头文件中声明的位置。截至目前,我们无法明确区分模板声明及其定义。

相关问题