2013-08-02 69 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函數放在頭文件中聲明的位置。截至目前,我們無法明確區分模板聲明及其定義。

相關問題